You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by me...@apache.org on 2019/10/28 09:01:40 UTC
[dubbo] branch cloud-native updated: [Update] Dubbo cloud native
(#5252)
This is an automated email from the ASF dual-hosted git repository.
mercyblitz pushed a commit to branch cloud-native
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/cloud-native by this push:
new 289e670 [Update] Dubbo cloud native (#5252)
289e670 is described below
commit 289e670422ff7bb19c5b07568f7fb23653938556
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Mon Oct 28 17:00:24 2019 +0800
[Update] Dubbo cloud native (#5252)
* Polish apache/dubbo#4542 : [Enhancement] Adapt the Java standard Event/Listener mechanism
* Polish apache/dubbo#4541 : [Feature] Add local File System DynamicConfigurationFactory‘s extension
* Polish apache#4541 : Bugfix
* Polish apache/dubbo#4541 : Optimization
* Polish apache/dubbo#4541 : Add the compatibility for PollingWatchService on the some platforms
* Polish apache/dubbo#4541 : Add delay publish without ThreadPoolExecutor
* Polish apache/dubbo#4541 : Refactor the extension name
* Polish apache/dubbo#4541 : Add remove ops
* Polish apache/dubbo#4541 : Add testable constructor
* Polish apache/dubbo#4541 : Add getConfigGroups method
* Polish apache/dubbo#4610 : [Refactor] Refactor the bootstrap module
* Polish apache/dubbo#4541 : Fix the nulling URL issue
* Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
* Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
* Polish apache/dubbo#4622 : Support multiple configcenters
* Polish apache/dubbo#4671 : ServiceNameMapping will not map the group, version and protocol
* update referenceCount log (#4683)
Add comments to support multiple shared connections
* Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring (#4688)
* #4685 修改代码if判断false问题 if (hasException == false)修改成if (!hasException) (#4695)
* Fixed Service annotation method parameters are not in effect (#4598)
* keep demo simple, and switch to use zookeeper as registry center (#4705)
* keep demo simple, and switch to use zookeeper as registry center
* remove comment
* @Reference auto-wires the instance of generic interface #4594 (#4677)
* try to shorten maven output to make travis build pass (#4710)
* use CountDownLatch to check zk registry if establish connection (#4589)
* Minor change
* Rename the extension name of WritableMetadataService
* Polish apache/dubbo#4759 : [Refactor] Change the signature of methods of MetadataService #4759
* Merge remote-tracking branch 'upstream/master' into dubbo-cloud-native
# Conflicts:
# dubbo-all/pom.xml
# dubbo-bom/pom.xml
# 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/RegistryConfig.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/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.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/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/dubbo-metadata-definition-protobuf/src/main/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilder.java
# dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.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
* Polish apache/dubbo#3984 : Add the implementation of Page<ServiceInstance> getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly)
* Code merge
* Fix the cases
* Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
# Conflicts:
# dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
# dubbo-metadata/dubbo-metadata-definition-protobuf/pom.xml
# dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
# dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java
# dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
* Refactor ConfigManager
* Refactor ConfigManager
* Resolve the issues on ConfigManager
* Refactor and add test-cases for ConfigManager
* Polish apache/dubbo#4774 : [Feature] Dubbo Cloud Native - To Support in Spring
* Polish apache/dubbo#4808 : [Feature] Add the registered/unregistered event mechanism ShutdownHook
* Polish apache/dubbo#4807 : [Feature] Add the callback mechanism ShutdownHook #4807
* Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
* Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
* Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
* Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
* Polish apache/dubbo#4807 : Add sort implementation
* Refactor
* Refactor
* Polish apache/dubbo#4845 : [Feature] Enhance the Event-Publishing feature to original ServiceDiscovery
* Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
# Conflicts:
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
* Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
# Conflicts:
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
* Polish apache/dubbo#4854 : [Feature] MetadataService supports the Dubbo protocol under auto-increased port
* Polish apache/dubbo#4857 : [Enhancement] Sync the Metadata storage type into ApplicationConfig
* Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent
* Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent
* Polish apache/dubbo#4873 : [Feature] Add a conditional EventListener into Event Module
* Polish apache/dubbo#4875 : [Feature] Refactor ServiceInstancesChangedListener
* Remove the cycle dependencies
* Remove the cycle dependencies
* Polish apache/dubbo#4903 : [Feature] Set source into the BeanDefinition of Dubbo Config
* Polish apache/dubbo#4902 : [Feature] Dubbo Cloud Native to Spring XML scenario
* Polish apache/dubbo#4713 : Initial the new module and dependencies
* Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
* Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
* Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
* Polish apache/dubbo#4910 : [Feature] To suppoort DubboLifecycleComponentApplicationListener in Spring XML scenario
* Polish apache/dubbo#4713 : Add Service discovery implementation for Eureka #4713
* Polish apache/dubbo#4713 : Add Service registration and discovery implementation for Eureka
* Polish apache/dubbo#4713 : Add Service registration and discovery implementation for Eureka
* Polish apache/dubbo#4920 : [Refactor] Extract the common implementation for URLs' revision
* Refactor
* Polish apache/dubbo#4925 : ServiceDiscovery limits only one ServiceInstancesChangedListener each service
* Polish apache/dubbo#4925 : ServiceDiscovery limits only one ServiceInstancesChangedListener each service
* Remove useless classes
* Bugfix & Refactor ServiceDiscoveryRegistry
* Polish apache/dubbo#4937 : The calculation of Revision should add the parameters of URL
* Polish apache/dubbo#4940 : NacosDynamicConfiguration supports getConfigKeys method
* Polish apache/dubbo#4942 : Dubbo Cloud Native supports multiple protcols
* Polish apache/dubbo#4944 : [Feature] Simplify The metadata of URL for MetadataService
* Polish apache/dubbo#4947 : [Feature] Dubbo Cloud-Native supports the REST call to Non-Dubbo
* Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
# Conflicts:
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
* Refactor
* Update JavaDoc
* Polish apache/dubbo#4905 : Add test cases for Configuration
* Polish apache/dubbo#4905 : Add test cases for AbstractDynamicConfigurationFactory
* Polish apache/dubbo#4905 : Add test cases for ConfigChangeType
* Polish apache/dubbo#4905 : Add test cases for AbstractDynamicConfiguration
* Polish apache/dubbo#4905 : Add test cases for ConfigChangedEvent
* Polish apache/dubbo#4905 : Add test cases for ConfigChangedEvent
* Polish apache/dubbo#4905 : Add test cases for FileSystemDynamicConfiguration
* Polish apache/dubbo#4905 : Add test cases for FileSystemDynamicConfigurationFactory
* Polish apache/dubbo#4905 : Enhancement the robustness for FileSystemDynamicConfiguration
* Polish apache/dubbo#4905 : Add test cases for AdaptiveClassCodeGenerator
* Polish apache/dubbo#4905 : Add test cases for ExtensionLoader
* Polish apache/dubbo#4905 : Add test cases for ThrowableAction, ThrowableConsumer, ThrowableFunction
* Polish apache/dubbo#4905 : Add test cases for Prioritized
* Polish apache/dubbo#4905 : Add test cases for ShutdownHookCallbacks
* Polish apache/dubbo#4905 : Add test cases for DubboServiceLoader
* Polish apache/dubbo#4981 : Add dubbo-common
* Polish apache/dubbo#4907 : Add test cases for DubboServiceDestroyedEvent
* Polish apache/dubbo#4907 : Add test cases for DubboShutdownHookRegisteredEvent
* Polish apache/dubbo#4907 : Add test cases for DubboShutdownHookUnregisteredEvent
* Polish apache/dubbo#4907 : Add test cases for ReferenceConfigDestroyedEvent
* Polish apache/dubbo#4907 : Add test cases for ReferenceConfigInitializedEvent
* Polish apache/dubbo#4907 : Add test cases for ServiceInstancePortCustomizer
* Polish apache/dubbo#4907 : Add test cases for ConfigurableMetadataServiceExporter
* Polish apache/dubbo#4907 : bugfix for @EnableDubbo
* Polish apache/dubbo#4907 : add test cases for @EnableDubboLifecycle
* Update the version to be 2.7.5
* Polish apache/dubbo#5034 : update
* Polish apache/dubbo#5034 : Add TypeDefinition builders
* Polish apache/dubbo#5034 : Complete TypeDefinition builders
* Polish apache/dubbo#5034 : Add ModelUtils
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : Add Spring Web MVC
* Polish apache/dubbo#5034 : Refactor
* Polish apache/dubbo#5034 : bug fix
* Polish apache/dubbo#5034 : Add test cases
* Polish apache/dubbo#5034 : Add test cases
---
dubbo-common/pom.xml | 13 +-
.../org/apache/dubbo/common/convert/Converter.java | 55 +++
.../dubbo/common/convert/StringConverter.java} | 22 +-
.../apache/dubbo/common/function/Predicates.java | 115 +++++
.../org/apache/dubbo/common/function/Streams.java | 71 ++++
.../dubbo/common/lang/ShutdownHookCallbacks.java | 2 +-
.../apache/dubbo/common/utils/CollectionUtils.java | 19 +
...ceLoader.java => PrioritizedServiceLoader.java} | 6 +-
.../org/apache/dubbo/common/utils/StringUtils.java | 31 +-
.../dubbo/common/utils/DubboServiceLoaderTest.java | 4 +-
.../apache/dubbo/config/annotation/Service.java | 1 +
dubbo-dependencies-bom/pom.xml | 106 +++--
dubbo-metadata/dubbo-metadata-api/pom.xml | 2 +-
.../dubbo/metadata/rest/RequestMetadata.java | 225 ++++++++++
.../dubbo/metadata/rest/RestMethodMetadata.java | 187 +++++++++
.../dubbo/metadata/rest/ServiceRestMetadata.java | 103 +++++
.../store/BaseWritableMetadataService.java | 4 -
.../RemoteWritableMetadataServiceDelegate.java | 1 -
.../org/apache/dubbo/metadata/util/HttpUtils.java | 266 ++++++++++++
.../report/identifier/MetadataIdentifierTest.java | 1 -
.../store/InMemoryWritableMetadataServiceTest.java | 1 -
.../store/RemoteWritableMeatadataServiceTest.java | 3 -
dubbo-metadata/dubbo-metadata-processor/pom.xml | 161 +++++++
.../AbstractServiceAnnotationProcessor.java | 108 +++++
.../processing/ClassPathMetadataStorage.java | 105 +++++
...rviceDefinitionMetadataAnnotationProcessor.java | 60 +++
.../builder/ArrayTypeDefinitionBuilder.java | 50 +++
.../builder/CollectionTypeDefinitionBuilder.java | 61 +++
.../builder/DeclaredTypeDefinitionBuilder.java | 49 +++
.../builder/EnumTypeDefinitionBuilder.java | 55 +++
.../builder/GeneralTypeDefinitionBuilder.java | 65 +++
.../builder/MapTypeDefinitionBuilder.java | 62 +++
.../builder/MethodDefinitionBuilder.java | 53 +++
.../builder/PrimitiveTypeDefinitionBuilder.java | 48 +++
.../builder/ServiceDefinitionBuilder.java | 56 +++
.../builder/SimpleTypeDefinitionBuilder.java | 49 +++
.../processing/builder/TypeDefinitionBuilder.java | 89 ++++
.../AbstractAnnotatedMethodParameterProcessor.java | 52 +++
.../rest/AbstractServiceRestMetadataProcessor.java | 232 ++++++++++
.../rest/AnnotatedMethodParameterProcessor.java | 62 +++
.../rest/DefaultServiceRestMetadataProcessor.java | 59 +++
.../ServiceRestMetadataAnnotationProcessor.java | 87 ++++
.../rest/ServiceRestMetadataProcessor.java | 53 +++
.../rest/ServiceRestMetadataStorage.java | 66 +++
.../rest/jaxrs/DefaultValueParameterProcessor.java | 78 ++++
.../rest/jaxrs/FormParamParameterProcessor.java | 22 +-
.../rest/jaxrs/HeaderParamParameterProcessor.java | 50 +++
.../jaxrs/JAXRSServiceRestMetadataProcessor.java | 113 +++++
.../rest/jaxrs/MatrixParamParameterProcessor.java | 22 +-
.../jaxrs/ParamAnnotationParameterProcessor.java | 38 ++
.../rest/jaxrs/QueryParamParameterProcessor.java | 22 +-
...bstractRequestAnnotationParameterProcessor.java | 69 +++
.../springmvc/RequestHeaderParameterProcessor.java | 41 ++
.../springmvc/RequestParamParameterProcessor.java | 42 ++
.../SpringMvcServiceRestMetadataProcessor.java | 157 +++++++
.../processing/util/AnnotationUtils.java | 233 ++++++++++
.../annotation/processing/util/FieldUtils.java | 146 +++++++
.../annotation/processing/util/LoggerUtils.java | 31 +-
.../annotation/processing/util/MemberUtils.java | 94 +++++
.../annotation/processing/util/MethodUtils.java | 155 +++++++
.../processing/util/ServiceAnnotationUtils.java | 121 ++++++
.../annotation/processing/util/TypeUtils.java | 382 +++++++++++++++++
.../services/javax.annotation.processing.Processor | 2 +
...tation.processing.builder.TypeDefinitionBuilder | 7 +
...ocessing.rest.AnnotatedMethodParameterProcessor | 10 +
...on.processing.rest.ServiceRestMetadataProcessor | 3 +
.../AbstractAnnotationProcessingTest.java | 69 +++
.../builder/ArrayTypeDefinitionBuilderTest.java | 121 ++++++
.../CollectionTypeDefinitionBuilderTest.java | 105 +++++
.../builder/EnumTypeDefinitionBuilderTest.java | 67 +++
.../builder/GeneralTypeDefinitionBuilderTest.java | 67 +++
.../builder/MapTypeDefinitionBuilderTest.java | 134 ++++++
.../PrimitiveTypeDefinitionBuilderTest.java | 130 ++++++
.../builder/ServiceDefinitionBuilderTest.java | 64 +++
.../builder/SimpleTypeDefinitionBuilderTest.java | 146 +++++++
.../processing/model/ArrayTypeModel.java | 30 +-
.../processing/model/CollectionTypeModel.java | 34 +-
.../annotation/processing/model/Color.java | 38 +-
.../annotation/processing/model/MapTypeModel.java | 33 +-
.../annotation/processing/model/Model.java | 89 ++++
.../processing/model/PrimitiveTypeModel.java | 67 ++-
.../processing/model/SimpleTypeModel.java | 161 +++++++
.../processing/util/AnnotationUtilsTest.java | 232 ++++++++++
.../annotation/processing/util/FieldUtilsTest.java | 259 ++++++++++++
.../processing/util/LoggerUtilsTest.java | 34 +-
.../processing/util/MemberUtilsTest.java | 113 +++++
.../processing/util/MethodUtilsTest.java | 195 +++++++++
.../util/ServiceAnnotationUtilsTest.java | 136 ++++++
.../annotation/processing/util/TypeUtilsTest.java | 467 +++++++++++++++++++++
.../org/apache/dubbo/metadata/tools/Ancestor.java | 29 +-
.../org/apache/dubbo/metadata/tools/Compiler.java | 116 +++++
.../apache/dubbo/metadata/tools/CompilerTest.java | 25 +-
.../dubbo/metadata/tools/DefaultTestService.java | 63 +++
.../dubbo/metadata/tools/GenericTestService.java | 26 +-
.../org/apache/dubbo/metadata/tools/Parent.java | 59 ++-
.../apache/dubbo/metadata/tools/RestService.java | 34 +-
.../dubbo/metadata/tools/RestServiceTest.java | 21 +-
.../dubbo/metadata/tools/SpringRestService.java | 97 +++++
.../metadata/tools/SpringRestServiceTest.java | 19 +-
.../dubbo/metadata/tools/StandardRestService.java | 107 +++++
.../metadata/tools/StandardRestServiceTest.java | 19 +-
.../apache/dubbo/metadata/tools/TestProcessor.java | 46 ++
.../apache/dubbo/metadata/tools/TestService.java | 46 +-
.../dubbo/metadata/tools/TestServiceImpl.java | 37 +-
.../java/org/apache/dubbo/metadata/tools/User.java | 61 +++
dubbo-metadata/pom.xml | 1 +
.../registry/client/ServiceDiscoveryRegistry.java | 8 +-
.../CustomizableServiceInstanceListener.java | 2 +-
108 files changed, 7985 insertions(+), 380 deletions(-)
diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml
index d988195..80d1ee3 100644
--- a/dubbo-common/pom.xml
+++ b/dubbo-common/pom.xml
@@ -15,7 +15,8 @@
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
@@ -31,11 +32,19 @@
<skip_maven_deploy>false</skip_maven_deploy>
</properties>
<dependencies>
+
+ <!-- Java Extension Libs -->
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
@@ -44,11 +53,13 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
+
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
new file mode 100644
index 0000000..c4e8dbc
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import org.apache.dubbo.common.lang.Prioritized;
+
+import java.util.function.Function;
+
+/**
+ * An interface converts an source instance of type {@link S} to an target instance of type {@link T}
+ *
+ * @param <S> the source type
+ * @param <T> the target type
+ * @since 2.7.5
+ */
+public interface Converter<S, T> extends Function<S, T>, Prioritized {
+
+ /**
+ * Tests whether or not the specified the source type and the target type
+ *
+ * @param sourceType the source type
+ * @param targetType the target type
+ * @return <code>true</code> if support to convert
+ */
+ default boolean accept(Class<S> sourceType, Class<T> targetType) {
+ return true;
+ }
+
+ /**
+ * Converts an source instance of type {@link S} to an target instance of type {@link T}
+ *
+ * @param source an source instance of type {@link S}
+ * @return an target instance of type {@link T}
+ */
+ T convert(S source);
+
+ @Override
+ default T apply(S s) {
+ return convert(s);
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
index b3b27e6..ddb99a1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
@@ -14,27 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.common.convert;
/**
- * {@link DubboServiceLoader} Test
+ * A converter converts a {@link String} value to the target instance of type {@link T}
*
+ * @param <T> the target type
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
+public interface StringConverter<T> extends Converter<String, T> {
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java
new file mode 100644
index 0000000..7bc1b48
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.function;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import static java.lang.Boolean.TRUE;
+import static java.util.stream.Stream.of;
+
+/**
+ * The utilities class for Java {@link Predicate}
+ *
+ * @since 2.7.5
+ */
+public interface Predicates {
+
+ Predicate[] EMPTY_ARRAY = new Predicate[0];
+
+ /**
+ * {@link Predicate} always return <code>true</code>
+ *
+ * @param <T> the type to test
+ * @return <code>true</code>
+ */
+ static <T> Predicate<T> alwaysTrue() {
+ return e -> true;
+ }
+
+ /**
+ * {@link Predicate} always return <code>false</code>
+ *
+ * @param <T> the type to test
+ * @return <code>false</code>
+ */
+ static <T> Predicate<T> alwaysFalse() {
+ return e -> false;
+ }
+
+
+ static <E, T> Predicate<T> map(Function<E, Predicate<T>> function, E element) {
+ return function.apply(element);
+ }
+
+ //
+// static <E, T> Predicate<T> map(Function<E, Predicate<T>> function, E... elements) {
+// return and(predicates(function, elements));
+// }
+//
+
+ static <E, T> Predicate<T>[] predicates(Function<E, Predicate<T>> function, E... elements) {
+ return of(elements)
+ .map(e -> function.apply(e))
+ .toArray(Predicate[]::new);
+ }
+
+ static <E, T> Predicate<T>[] predicates(BiFunction<E, T, Predicate<T>> function, T value, E... elements) {
+ return of(elements)
+ .map(e -> function.apply(e, value))
+ .toArray(Predicate[]::new);
+ }
+
+ static <E, T> Predicate<T> predicate(BiFunction<E, T, Predicate<T>> function, T value, E... elements) {
+ return and(predicates(function, value, elements));
+ }
+
+ /**
+ * Convert a {@link Function} to {@link Predicate}
+ *
+ * @param function a {@link Function}
+ * @param <T> the type to test
+ * @return non-null
+ */
+ static <T> Predicate<T> predicate(Function<T, Boolean> function) {
+ return t -> TRUE.equals(function.apply(t));
+ }
+
+ /**
+ * a composed predicate that represents a short-circuiting logical AND of {@link Predicate predicates}
+ *
+ * @param predicates {@link Predicate predicates}
+ * @param <T> the type to test
+ * @return non-null
+ */
+ static <T> Predicate<T> and(Predicate<T>... predicates) {
+ return of(predicates).reduce((a, b) -> a.and(b)).orElseGet(Predicates::alwaysTrue);
+ }
+
+ /**
+ * a composed predicate that represents a short-circuiting logical OR of {@link Predicate predicates}
+ *
+ * @param predicates {@link Predicate predicates}
+ * @param <T> the detected type
+ * @return non-null
+ */
+ static <T> Predicate<T> or(Predicate<T>... predicates) {
+ return of(predicates).reduce((a, b) -> a.or(b)).orElse(e -> true);
+ }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.java
new file mode 100644
index 0000000..65e4fa6
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.function;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.StreamSupport.stream;
+import static org.apache.dubbo.common.function.Predicates.and;
+import static org.apache.dubbo.common.function.Predicates.or;
+
+/**
+ * The utilities class for {@link Stream}
+ *
+ * @since 2.7.5
+ */
+public interface Streams {
+
+ static <T, S extends Iterable<T>> Stream<T> filterStream(S values, Predicate<T> predicate) {
+ return stream(values.spliterator(), false).filter(predicate);
+ }
+
+ static <T, S extends Iterable<T>> List<T> filterList(S values, Predicate<T> predicate) {
+ return filterStream(values, predicate).collect(toList());
+ }
+
+ static <T, S extends Iterable<T>> Set<T> filterSet(S values, Predicate<T> predicate) {
+ // new Set with insertion order
+ return filterStream(values, predicate).collect(LinkedHashSet::new, Set::add, Set::addAll);
+ }
+
+ static <T, S extends Iterable<T>> S filter(S values, Predicate<T> predicate) {
+ final boolean isSet = Set.class.isAssignableFrom(values.getClass());
+ return (S) (isSet ? filterSet(values, predicate) : filterList(values, predicate));
+ }
+
+ static <T, S extends Iterable<T>> S filterAll(S values, Predicate<T>... predicates) {
+ return filter(values, and(predicates));
+ }
+
+ static <T, S extends Iterable<T>> S filterAny(S values, Predicate<T>... predicates) {
+ return filter(values, or(predicates));
+ }
+
+ static <T> T filterFirst(Iterable<T> values, Predicate<T>... predicates) {
+ return stream(values.spliterator(), false)
+ .filter(and(predicates))
+ .findFirst()
+ .orElse(null);
+ }
+}
+
+
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
index a5555e8..41d6dee 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
@@ -22,7 +22,7 @@ import java.util.List;
import static java.util.Collections.sort;
import static org.apache.dubbo.common.function.ThrowableAction.execute;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.load;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
/**
* The compose {@link ShutdownHookCallback} class to manipulate one and more {@link ShutdownHookCallback} instances
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
index 40baecd..d3d8cc0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
@@ -21,8 +21,14 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableSet;
public class CollectionUtils {
@@ -217,4 +223,17 @@ public class CollectionUtils {
return !isEmptyMap(map);
}
+ /**
+ * Convert to multiple values to be {@link HashSet}
+ *
+ * @param values one or more values
+ * @param <T> the type of <code>values</code>
+ * @return read-only {@link HashSet}
+ */
+ public static <T> Set<T> asHashSet(T... values) {
+ if (values == null || values.length < 1) {
+ return emptySet();
+ }
+ return unmodifiableSet(new HashSet(asList(values)));
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
similarity index 95%
rename from dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
index 637440a..dcbcd27 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
@@ -27,13 +27,13 @@ import static java.util.stream.Collectors.toList;
import static java.util.stream.StreamSupport.stream;
/**
- * An extension class of {@link ServiceLoader} to help the ease for use of Dubbo services/components
+ * An extension class of {@link ServiceLoader} with {@link Prioritized} feature
*
* @see ServiceLoader
* @see Prioritized
* @since 2.7.5
*/
-public class DubboServiceLoader {
+public interface PrioritizedServiceLoader {
/**
* Load a {@link Stream stream} of services by the specified {@link Class type} and {@link ClassLoader}
@@ -51,7 +51,7 @@ public class DubboServiceLoader {
ClassLoader actualClassLoader = classLoader;
if (actualClassLoader == null) {
- actualClassLoader = DubboServiceLoader.class.getClassLoader();
+ actualClassLoader = PrioritizedServiceLoader.class.getClassLoader();
}
ServiceLoader<S> serviceLoader = ServiceLoader.load(serviceClass, actualClassLoader);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
index 53557a3..c3d81a1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
@@ -32,6 +32,7 @@ import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static java.lang.String.valueOf;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX;
@@ -57,6 +58,34 @@ public final class StringUtils {
private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$");
private static final int PAD_LIMIT = 8192;
+ /**
+ * @since 2.7.5
+ */
+ public static final char EQUAL_CHAR = '=';
+
+ public static final String EQUAL = valueOf(EQUAL_CHAR);
+
+ public static final char AND_CHAR = '&';
+
+ public static final String AND = valueOf(AND_CHAR);
+
+ public static final char SEMICOLON_CHAR = ';';
+
+ public static final String SEMICOLON = valueOf(SEMICOLON_CHAR);
+
+ public static final char QUESTION_MASK_CHAR = '?';
+
+ public static final String QUESTION_MASK = valueOf(QUESTION_MASK_CHAR);
+
+ public static final char SLASH_CHAR = '/';
+
+ public static final String SLASH = valueOf(SLASH_CHAR);
+
+ /**
+ * The empty value
+ */
+ public static final String EMPTY_VALUE = "";
+
private StringUtils() {
}
@@ -819,7 +848,7 @@ public final class StringUtils {
if (str != null && !isEmpty(str)) {
int sz = str.length();
- for(int i = 0; i < sz; ++i) {
+ for (int i = 0; i < sz; ++i) {
if (!Character.isUpperCase(str.charAt(i))) {
return false;
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
index b3b27e6..d2d0cf6 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
@@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test;
import java.util.List;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
- * {@link DubboServiceLoader} Test
+ * {@link PrioritizedServiceLoader} Test
*
* @since 2.7.5
*/
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
index 8b13373..867d5d8 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
@@ -274,6 +274,7 @@ public @interface Service {
/**
* methods support
+ *
* @return
*/
Method[] methods() default {};
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 3c5b432..f95cee2 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -89,6 +89,16 @@
</issueManagement>
<properties>
+ <!-- Java Extension Libs -->
+ <servlet_version>3.1.0</servlet_version>
+ <annotation_version>1.3.1</annotation_version>
+ <validation_version>1.1.0.Final</validation_version>
+ <rs_api_version>2.0</rs_api_version>
+ <jcache_version>1.0.0</jcache_version>
+ <jaxb_version>2.2.7</jaxb_version>
+ <activation_version>1.2.0</activation_version>
+ <portlet_version>2.0</portlet_version>
+
<!-- Common libs -->
<spring_version>4.3.16.RELEASE</spring_version>
<javassist_version>3.20.0-GA</javassist_version>
@@ -110,12 +120,10 @@
<thrift_version>0.12.0</thrift_version>
<hessian_version>4.0.38</hessian_version>
<protobuf-java_version>3.6.0</protobuf-java_version>
- <servlet_version>3.1.0</servlet_version>
+
<jetty_version>9.4.11.v20180605</jetty_version>
- <validation_version>1.1.0.Final</validation_version>
<hibernate_validator_version>5.4.1.Final</hibernate_validator_version>
<jel_version>3.0.1-b08</jel_version>
- <jcache_version>1.0.0</jcache_version>
<kryo_version>4.0.1</kryo_version>
<kryo_serializers_version>0.42</kryo_serializers_version>
<fst_version>2.48-jdk-6</fst_version>
@@ -125,7 +133,6 @@
<commons_lang3_version>3.8.1</commons_lang3_version>
<protostuff_version>1.5.9</protostuff_version>
- <rs_api_version>2.0</rs_api_version>
<resteasy_version>3.0.19.Final</resteasy_version>
<tomcat_embed_version>8.5.31</tomcat_embed_version>
<jetcd_version>0.3.0</jetcd_version>
@@ -144,8 +151,6 @@
<!-- Eureka -->
<eureka.version>1.9.12</eureka.version>
- <jaxb_version>2.2.7</jaxb_version>
- <activation_version>1.2.0</activation_version>
<test_container_version>1.11.2</test_container_version>
<etcd_launcher_version>0.3.0</etcd_launcher_version>
<hessian_lite_version>3.2.5</hessian_lite_version>
@@ -157,13 +162,62 @@
<gson_version>2.8.5</gson_version>
<jsonrpc_version>1.2.0</jsonrpc_version>
<mortbay_jetty_version>6.1.26</mortbay_jetty_version>
- <portlet_version>2.0</portlet_version>
<maven_flatten_version>1.1.0</maven_flatten_version>
<revision>2.7.5-cloudnative-SNAPSHOT</revision>
</properties>
<dependencyManagement>
<dependencies>
+
+ <!-- Java Extension Libs -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <version>${annotation_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>${validation_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.cache</groupId>
+ <artifactId>cache-api</artifactId>
+ <version>${jcache_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>${rs_api_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>${jaxb_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.activation</groupId>
+ <artifactId>javax.activation-api</artifactId>
+ <version>${activation_version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>${portlet_version}</version>
+ </dependency>
+
<!-- Common libs -->
<dependency>
<groupId>org.springframework</groupId>
@@ -311,11 +365,7 @@
<artifactId>protobuf-java-util</artifactId>
<version>${protobuf-java_version}</version>
</dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>${servlet_version}</version>
- </dependency>
+
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
@@ -332,11 +382,7 @@
<version>${mortbay_jetty_version}</version>
<optional>true</optional>
</dependency>
- <dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>${validation_version}</version>
- </dependency>
+
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
@@ -348,11 +394,6 @@
<version>${jel_version}</version>
</dependency>
<dependency>
- <groupId>javax.cache</groupId>
- <artifactId>cache-api</artifactId>
- <version>${jcache_version}</version>
- </dependency>
- <dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo_version}</version>
@@ -383,11 +424,6 @@
<version>${protostuff_version}</version>
</dependency>
<dependency>
- <groupId>javax.ws.rs</groupId>
- <artifactId>javax.ws.rs-api</artifactId>
- <version>${rs_api_version}</version>
- </dependency>
- <dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>${resteasy_version}</version>
@@ -513,11 +549,6 @@
<!-- for dubbo-rpc-webservice -->
<dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>${jaxb_version}</version>
- </dependency>
- <dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb_version}</version>
@@ -527,11 +558,7 @@
<artifactId>jaxb-core</artifactId>
<version>${jaxb_version}</version>
</dependency>
- <dependency>
- <groupId>javax.activation</groupId>
- <artifactId>javax.activation-api</artifactId>
- <version>${activation_version}</version>
- </dependency>
+
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
@@ -620,11 +647,6 @@
<artifactId>jsonrpc4j</artifactId>
<version>${jsonrpc_version}</version>
</dependency>
- <dependency>
- <groupId>javax.portlet</groupId>
- <artifactId>portlet-api</artifactId>
- <version>${portlet_version}</version>
- </dependency>
<!-- for dubbo-configcenter-etcd -->
<dependency>
<groupId>io.etcd</groupId>
diff --git a/dubbo-metadata/dubbo-metadata-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml
index 8c9a80c..cb3002a 100644
--- a/dubbo-metadata/dubbo-metadata-api/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-api/pom.xml
@@ -44,7 +44,7 @@
<artifactId>dubbo-cluster</artifactId>
<version>${project.parent.version}</version>
</dependency>
-
+
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java
new file mode 100644
index 0000000..830840d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest;
+
+
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import static java.util.Collections.unmodifiableMap;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+import static org.apache.dubbo.metadata.util.HttpUtils.normalizePath;
+
+/**
+ * The metadata class for REST request
+ *
+ * @since 2.7.5
+ */
+public class RequestMetadata implements Serializable {
+
+ private static final long serialVersionUID = -240099840085329958L;
+
+ private String method;
+
+ private String path;
+
+ private Map<String, List<String>> params = new LinkedHashMap<>();
+
+ private Map<String, List<String>> headers = new LinkedHashMap<>();
+
+ private Set<String> consumes = new LinkedHashSet<>();
+
+ private Set<String> produces = new LinkedHashSet<>();
+
+ /**
+ * Default Constructor
+ */
+ public RequestMetadata() {
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method == null ? null : method.toUpperCase();
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = normalizePath(path);
+ }
+
+ public Map<String, List<String>> getParams() {
+ return unmodifiableMap(params);
+ }
+
+ public void setParams(Map<String, List<String>> params) {
+ params(params);
+ }
+
+ private static void add(Map<String, List<String>> multiValueMap, String key, String value) {
+ if (isBlank(key)) {
+ return;
+ }
+ List<String> values = get(multiValueMap, key, true);
+ values.add(value);
+ }
+
+ private static <T extends Collection<String>> void addAll(Map<String, List<String>> multiValueMap,
+ Map<String, T> source) {
+ for (Map.Entry<String, T> entry : source.entrySet()) {
+ String key = entry.getKey();
+ for (String value : entry.getValue()) {
+ add(multiValueMap, key, value);
+ }
+ }
+ }
+
+ private static String getFirst(Map<String, List<String>> multiValueMap, String key) {
+ List<String> values = get(multiValueMap, key);
+ return CollectionUtils.isNotEmpty(values) ? values.get(0) : null;
+ }
+
+ private static List<String> get(Map<String, List<String>> multiValueMap, String key) {
+ return get(multiValueMap, key, false);
+ }
+
+ private static List<String> get(Map<String, List<String>> multiValueMap, String key, boolean createIfAbsent) {
+ return createIfAbsent ? multiValueMap.computeIfAbsent(key, k -> new LinkedList<>()) : multiValueMap.get(key);
+ }
+
+ public Map<String, List<String>> getHeaders() {
+ return unmodifiableMap(headers);
+ }
+
+ public void setHeaders(Map<String, List<String>> headers) {
+ headers(headers);
+ }
+
+ public Set<String> getConsumes() {
+ return consumes;
+ }
+
+ public void setConsumes(Set<String> consumes) {
+ this.consumes = consumes;
+ }
+
+ public Set<String> getProduces() {
+ return produces;
+ }
+
+ public void setProduces(Set<String> produces) {
+ this.produces = produces;
+ }
+
+ public Set<String> getParamNames() {
+ return params.keySet();
+ }
+
+ public Set<String> getHeaderNames() {
+ return headers.keySet();
+ }
+
+// public List<MediaType> getConsumeMediaTypes() {
+// return toMediaTypes(consumes);
+// }
+//
+// public List<MediaType> getProduceMediaTypes() {
+// return toMediaTypes(produces);
+// }
+
+ public String getParameter(String name) {
+ return this.getFirst(params, name);
+ }
+
+ public String getHeader(String name) {
+ return this.getFirst(headers, name);
+ }
+
+ public RequestMetadata addParam(String name, String value) {
+ add(params, name, value);
+ return this;
+ }
+
+ public RequestMetadata addHeader(String name, String value) {
+ add(headers, name, value);
+ return this;
+ }
+
+ private <T extends Collection<String>> RequestMetadata params(Map<String, T> params) {
+ addAll(this.params, params);
+ return this;
+ }
+
+ private <T extends Collection<String>> RequestMetadata headers(Map<String, List<String>> headers) {
+ if (headers != null && !headers.isEmpty()) {
+ Map<String, List<String>> httpHeaders = new LinkedHashMap<>();
+ // Add all headers
+ addAll(headers, httpHeaders);
+ // Handles "Content-Type" and "Accept" headers if present
+// mediaTypes(httpHeaders, HttpHeaders.CONTENT_TYPE, this.consumes);
+// mediaTypes(httpHeaders, HttpHeaders.ACCEPT, this.produces);
+ this.headers.putAll(httpHeaders);
+ }
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof RequestMetadata)) {
+ return false;
+ }
+ RequestMetadata that = (RequestMetadata) o;
+ return Objects.equals(method, that.method) && Objects.equals(path, that.path)
+ && Objects.equals(consumes, that.consumes)
+ && Objects.equals(produces, that.produces) &&
+ // Metadata should not compare the values
+ Objects.equals(getParamNames(), that.getParamNames())
+ && Objects.equals(getHeaderNames(), that.getHeaderNames());
+
+ }
+
+ @Override
+ public int hashCode() {
+ // The values of metadata should not use for the hashCode() method
+ return Objects.hash(method, path, consumes, produces, getParamNames(),
+ getHeaderNames());
+ }
+
+ @Override
+ public String toString() {
+ return "RequestMetadata{" + "method='" + method + '\'' + ", path='" + path + '\''
+ + ", params=" + params + ", headers=" + headers + ", consumes=" + consumes
+ + ", produces=" + produces + '}';
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
new file mode 100644
index 0000000..e43fce7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static java.util.Collections.emptyList;
+
+/**
+ * The metadata class for {@link RequestMetadata HTTP(REST) request} and
+ * its binding {@link MethodDefinition method definition}
+ *
+ * @since 2.7.5
+ */
+public class RestMethodMetadata implements Serializable {
+
+ private static final long serialVersionUID = 2935252016200830694L;
+
+ private MethodDefinition method;
+
+ private RequestMetadata request;
+
+ private Integer urlIndex;
+
+ private Integer bodyIndex;
+
+ private Integer headerMapIndex;
+
+ private String bodyType;
+
+ private Map<Integer, Collection<String>> indexToName;
+
+ private List<String> formParams;
+
+ private Map<Integer, Boolean> indexToEncoded;
+
+ public MethodDefinition getMethod() {
+ if (method == null) {
+ method = new MethodDefinition();
+ }
+ return method;
+ }
+
+ public void setMethod(MethodDefinition method) {
+ this.method = method;
+ }
+
+ public RequestMetadata getRequest() {
+ if (request == null) {
+ request = new RequestMetadata();
+ }
+ return request;
+ }
+
+ public void setRequest(RequestMetadata request) {
+ this.request = request;
+ }
+
+ public Integer getUrlIndex() {
+ return urlIndex;
+ }
+
+ public void setUrlIndex(Integer urlIndex) {
+ this.urlIndex = urlIndex;
+ }
+
+ public Integer getBodyIndex() {
+ return bodyIndex;
+ }
+
+ public void setBodyIndex(Integer bodyIndex) {
+ this.bodyIndex = bodyIndex;
+ }
+
+ public Integer getHeaderMapIndex() {
+ return headerMapIndex;
+ }
+
+ public void setHeaderMapIndex(Integer headerMapIndex) {
+ this.headerMapIndex = headerMapIndex;
+ }
+
+ public String getBodyType() {
+ return bodyType;
+ }
+
+ public void setBodyType(String bodyType) {
+ this.bodyType = bodyType;
+ }
+
+ public Map<Integer, Collection<String>> getIndexToName() {
+ if (indexToName == null) {
+ indexToName = new HashMap<>();
+ }
+ return indexToName;
+ }
+
+ public void setIndexToName(Map<Integer, Collection<String>> indexToName) {
+ this.indexToName = indexToName;
+ }
+
+ public void addIndexToName(Integer index, String name) {
+ Map<Integer, Collection<String>> indexToName = getIndexToName();
+ Collection<String> parameterNames = indexToName.computeIfAbsent(index, i -> new ArrayList<>(1));
+ parameterNames.add(name);
+ }
+
+ public boolean hasIndexedName(Integer index, String name) {
+ Map<Integer, Collection<String>> indexToName = getIndexToName();
+ return indexToName.getOrDefault(index, emptyList()).contains(name);
+ }
+
+ public List<String> getFormParams() {
+ return formParams;
+ }
+
+ public void setFormParams(List<String> formParams) {
+ this.formParams = formParams;
+ }
+
+ public Map<Integer, Boolean> getIndexToEncoded() {
+ return indexToEncoded;
+ }
+
+ public void setIndexToEncoded(Map<Integer, Boolean> indexToEncoded) {
+ this.indexToEncoded = indexToEncoded;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RestMethodMetadata)) return false;
+ RestMethodMetadata that = (RestMethodMetadata) o;
+ return Objects.equals(getMethod(), that.getMethod()) &&
+ Objects.equals(getRequest(), that.getRequest()) &&
+ Objects.equals(getUrlIndex(), that.getUrlIndex()) &&
+ Objects.equals(getBodyIndex(), that.getBodyIndex()) &&
+ Objects.equals(getHeaderMapIndex(), that.getHeaderMapIndex()) &&
+ Objects.equals(getBodyType(), that.getBodyType()) &&
+ Objects.equals(getIndexToName(), that.getIndexToName()) &&
+ Objects.equals(getFormParams(), that.getFormParams()) &&
+ Objects.equals(getIndexToEncoded(), that.getIndexToEncoded());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getMethod(), getRequest(), getUrlIndex(), getBodyIndex(), getHeaderMapIndex(), getBodyType(), getIndexToName(), getFormParams(), getIndexToEncoded());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("RestMethodMetadata{");
+ sb.append("method=").append(method);
+ sb.append(", request=").append(request);
+ sb.append(", urlIndex=").append(urlIndex);
+ sb.append(", bodyIndex=").append(bodyIndex);
+ sb.append(", headerMapIndex=").append(headerMapIndex);
+ sb.append(", bodyType='").append(bodyType).append('\'');
+ sb.append(", indexToName=").append(indexToName);
+ sb.append(", formParams=").append(formParams);
+ sb.append(", indexToEncoded=").append(indexToEncoded);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
new file mode 100644
index 0000000..34cddd6
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * The metadata class for {@link RequestMetadata HTTP(REST) request} and
+ * its binding Dubbo service metadata
+ *
+ * @since 2.7.5
+ */
+public class ServiceRestMetadata implements Serializable {
+
+ private static final long serialVersionUID = -4549723140727443569L;
+
+ private String serviceInterface;
+
+ private String version;
+
+ private String group;
+
+ private Set<RestMethodMetadata> meta;
+
+ public String getServiceInterface() {
+ return serviceInterface;
+ }
+
+ public void setServiceInterface(String serviceInterface) {
+ this.serviceInterface = serviceInterface;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public Set<RestMethodMetadata> getMeta() {
+ if (meta == null) {
+ meta = new LinkedHashSet<>();
+ }
+ return meta;
+ }
+
+ public void setMeta(Set<RestMethodMetadata> meta) {
+ this.meta = meta;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ServiceRestMetadata)) return false;
+ ServiceRestMetadata that = (ServiceRestMetadata) o;
+ return Objects.equals(getServiceInterface(), that.getServiceInterface()) &&
+ Objects.equals(getVersion(), that.getVersion()) &&
+ Objects.equals(getGroup(), that.getGroup()) &&
+ Objects.equals(getMeta(), that.getMeta());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getServiceInterface(), getVersion(), getGroup(), getMeta());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("ServiceRestMetadata{");
+ sb.append("serviceInterface='").append(serviceInterface).append('\'');
+ sb.append(", version='").append(version).append('\'');
+ sb.append(", group='").append(group).append('\'');
+ sb.append(", meta=").append(meta);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
index c751226..764d035 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
@@ -4,17 +4,13 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.MetadataService;
-import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
import java.util.Collection;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.function.BiConsumer;
import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
/**
* @author cvictory ON 2019-08-14
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
index eed9e43..448ddc8 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
@@ -1,7 +1,6 @@
package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.metadata.WritableMetadataService;
import java.util.SortedSet;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java
new file mode 100644
index 0000000..20095a4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.util;
+
+
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.common.utils.StringUtils.AND;
+import static org.apache.dubbo.common.utils.StringUtils.EQUAL;
+import static org.apache.dubbo.common.utils.StringUtils.QUESTION_MASK;
+import static org.apache.dubbo.common.utils.StringUtils.SLASH;
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+import static org.apache.dubbo.common.utils.StringUtils.replace;
+
+/**
+ * Http Utilities class
+ *
+ * @since 2.7.5
+ */
+public abstract class HttpUtils {
+
+ private static final String UTF_8 = "UTF-8";
+
+ /**
+ * HTTP GET method.
+ */
+ public static final String GET = "GET";
+ /**
+ * HTTP POST method.
+ */
+ public static final String POST = "POST";
+ /**
+ * HTTP PUT method.
+ */
+ public static final String PUT = "PUT";
+ /**
+ * HTTP DELETE method.
+ */
+ public static final String DELETE = "DELETE";
+ /**
+ * HTTP HEAD method.
+ */
+ public static final String HEAD = "HEAD";
+ /**
+ * HTTP OPTIONS method.
+ */
+ public static final String OPTIONS = "OPTIONS";
+
+ /**
+ * The HTTP methods to support
+ */
+ public static final Set<String> HTTP_METHODS = unmodifiableSet(new LinkedHashSet<>(asList(
+ GET, POST, POST, PUT, DELETE, HEAD, OPTIONS
+ )));
+
+
+ public static String buildPath(String rootPath, String... subPaths) {
+
+ Set<String> paths = new LinkedHashSet<>();
+ paths.add(rootPath);
+ paths.addAll(asList(subPaths));
+
+ return normalizePath(paths.stream()
+ .filter(StringUtils::isNotEmpty)
+ .collect(Collectors.joining(SLASH)));
+ }
+
+ /**
+ * Normalize path:
+ * <ol>
+ * <li>To remove query string if presents</li>
+ * <li>To remove duplicated slash("/") if exists</li>
+ * </ol>
+ *
+ * @param path path to be normalized
+ * @return a normalized path if required
+ */
+ public static String normalizePath(String path) {
+ if (isEmpty(path)) {
+ return SLASH;
+ }
+ String normalizedPath = path;
+ int index = normalizedPath.indexOf(QUESTION_MASK);
+ if (index > -1) {
+ normalizedPath = normalizedPath.substring(0, index);
+ }
+ return replace(normalizedPath, "//", "/");
+ }
+
+// /**
+// * Get Parameters from the specified query string.
+// * <p>
+// *
+// * @param queryString The query string
+// * @return The query parameters
+// */
+// public static MultivaluedMap<String, String> getParameters(String queryString) {
+// return getParameters(split(queryString, AND_CHAR));
+// }
+
+// /**
+// * Get Parameters from the specified pairs of name-value.
+// * <p>
+// *
+// * @param pairs The pairs of name-value
+// * @return The query parameters
+// */
+// public static MultivaluedMap<String, String> getParameters(Iterable<String> pairs) {
+// MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
+// if (pairs != null) {
+// for (String pair : pairs) {
+// String[] nameAndValue = split(pair, EQUAL_CHAR);
+// String name = decode(nameAndValue[0]);
+// String value = nameAndValue.length < 2 ? null : nameAndValue[1];
+// value = decode(value);
+// addParam(parameters, name, value);
+// }
+// }
+// return parameters;
+// }
+
+// /**
+// * Get Parameters from the specified pairs of name-value.
+// * <p>
+// *
+// * @param pairs The pairs of name-value
+// * @return The query parameters
+// */
+// public static MultivaluedMap<String, String> getParameters(String... pairs) {
+// return getParameters(asList(pairs));
+// }
+
+ // /**
+ // * Parse a read-only {@link MultivaluedMap} of {@link HttpCookie} from {@link
+ // HttpHeaders}
+ // *
+ // * @param httpHeaders {@link HttpHeaders}
+ // * @return non-null, the key is a cookie name , the value is {@link HttpCookie}
+ // */
+ // public static MultivaluedMap<String, HttpCookie> parseCookies(HttpHeaders
+ // httpHeaders) {
+ //
+ // String cookie = httpHeaders.getFirst(COOKIE);
+ //
+ // String[] cookieNameAndValues = StringUtils.delimitedListToStringArray(cookie,
+ // SEMICOLON);
+ //
+ // MultivaluedMap<String, HttpCookie> cookies = new
+ // LinkedMultiValueMap<>(cookieNameAndValues.length);
+ //
+ // for (String cookeNameAndValue : cookieNameAndValues) {
+ // String[] nameAndValue =
+ // delimitedListToStringArray(trimWhitespace(cookeNameAndValue), EQUAL);
+ // String name = nameAndValue[0];
+ // String value = nameAndValue.length < 2 ? null : nameAndValue[1];
+ // HttpCookie httpCookie = new HttpCookie(name, value);
+ // cookies.add(name, httpCookie);
+ // }
+ //
+ // return cookies;
+ // }
+
+ /**
+ * To the name and value line sets
+ *
+ * @param nameAndValuesMap the map of name and values
+ * @return non-null
+ */
+ public static Set<String> toNameAndValuesSet(
+ Map<String, List<String>> nameAndValuesMap) {
+ Set<String> nameAndValues = new LinkedHashSet<>();
+ for (Map.Entry<String, List<String>> entry : nameAndValuesMap.entrySet()) {
+ String name = entry.getKey();
+ List<String> values = entry.getValue();
+ for (String value : values) {
+ String nameAndValue = name + EQUAL + value;
+ nameAndValues.add(nameAndValue);
+ }
+ }
+ return nameAndValues;
+ }
+
+ public static String[] toNameAndValues(Map<String, List<String>> nameAndValuesMap) {
+ return toNameAndValuesSet(nameAndValuesMap).toArray(new String[0]);
+ }
+
+ /**
+ * Generate a string of query string from the specified request parameters {@link Map}
+ *
+ * @param params the specified request parameters {@link Map}
+ * @return non-null
+ */
+ public static String toQueryString(Map<String, List<String>> params) {
+ StringBuilder builder = new StringBuilder();
+ for (String line : toNameAndValuesSet(params)) {
+ builder.append(line).append(AND);
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Decode value
+ *
+ * @param value the value requires to decode
+ * @return the decoded value
+ */
+ public static String decode(String value) {
+ if (value == null) {
+ return value;
+ }
+ String decodedValue = value;
+ try {
+ decodedValue = URLDecoder.decode(value, UTF_8);
+ } catch (UnsupportedEncodingException ex) {
+ }
+ return decodedValue;
+ }
+
+ /**
+ * encode value
+ *
+ * @param value the value requires to encode
+ * @return the encoded value
+ */
+ public static String encode(String value) {
+ String encodedValue = value;
+ try {
+ encodedValue = URLEncoder.encode(value, UTF_8);
+ } catch (UnsupportedEncodingException ex) {
+ }
+ return encodedValue;
+ }
+
+// private static void addParam(MultivaluedMap<String, String> paramsMap, String name,
+// String value) {
+// String paramValue = trim(value);
+// if (isEmpty(paramValue)) {
+// paramValue = EMPTY_VALUE;
+// }
+// paramsMap.add(trim(name), paramValue);
+// }
+}
diff --git 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
index 90df3db..3a58933 100644
--- 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
@@ -17,7 +17,6 @@
package org.apache.dubbo.metadata.report.identifier;
import org.apache.dubbo.metadata.MetadataConstants;
-import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
index c032843..2bd9137 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
@@ -2,7 +2,6 @@ package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
index b6dfa48..94cc577 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
@@ -34,8 +33,6 @@ import org.junit.jupiter.api.Test;
import java.util.Map;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
-
/**
* 2018/9/14
*/
diff --git a/dubbo-metadata/dubbo-metadata-processor/pom.xml b/dubbo-metadata/dubbo-metadata-processor/pom.xml
new file mode 100644
index 0000000..9be4ddb
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata</artifactId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-metadata-processor</artifactId>
+ <packaging>jar</packaging>
+ <name>dubbo-metadata-processor</name>
+ <description>The metadata processor module of Dubbo project</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-api</artifactId>
+ <version>${project.parent.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-cluster</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-common</artifactId>
+ <version>${project.parent.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.alibaba</groupId>
+ <artifactId>hessian-lite</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.esotericsoftware</groupId>
+ <artifactId>kryo</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>de.javakaffee</groupId>
+ <artifactId>kryo-serializers</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>de.ruedigermoeller</groupId>
+ <artifactId>fst</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </exclusion>
+ </exclusions>
+
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+
+ <!-- Test -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-config-api</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-registry-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-monitor-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-remoting-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-injvm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-filter-validation</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-filter-cache</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- JAX-RS API -->
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- Spring Web MVC -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java
new file mode 100644
index 0000000..e5af1ad
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SUPPORTED_ANNOTATION_TYPES;
+
+/**
+ * Abstract {@link Processor} for the classes that were annotated by Dubbo's @Service
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractServiceAnnotationProcessor extends AbstractProcessor {
+
+ protected Elements elements;
+
+ private List<? extends Element> objectMembers;
+
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ this.elements = processingEnv.getElementUtils();
+ this.objectMembers = elements.getAllMembers(elements.getTypeElement(Object.class.getName()));
+ }
+
+ protected List<? extends Element> getActualMembers(TypeElement type) {
+ List<? extends Element> members = new LinkedList<>(elements.getAllMembers(type));
+ members.removeAll(objectMembers);
+ return members;
+ }
+
+ protected List<? extends ExecutableElement> getActualMethods(TypeElement type) {
+ return methodsIn(getActualMembers(type));
+ }
+
+ protected Map<String, ExecutableElement> getActualMethodsMap(TypeElement type) {
+ Map<String, ExecutableElement> methodsMap = new HashMap<>();
+ getActualMethods(type).forEach(method -> {
+ methodsMap.put(method.toString(), method);
+ });
+ return methodsMap;
+ }
+
+ public static String getMethodSignature(ExecutableElement method) {
+ if (!ElementKind.METHOD.equals(method.getKind())) {
+ throw new IllegalArgumentException("The argument must be Method Kind");
+ }
+
+ StringBuilder methodSignatureBuilder = new StringBuilder();
+
+ method.getModifiers().forEach(member -> {
+ methodSignatureBuilder.append(member).append(" ");
+ });
+
+ methodSignatureBuilder.append(method.getReturnType())
+ .append(" ")
+ .append(method.toString());
+
+ return methodSignatureBuilder.toString();
+ }
+
+ protected TypeElement getTypeElement(CharSequence className) {
+ return elements.getTypeElement(className);
+ }
+
+ protected PackageElement getPackageElement(Element type) {
+ return this.elements.getPackageOf(type);
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public final Set<String> getSupportedAnnotationTypes() {
+ return SUPPORTED_ANNOTATION_TYPES;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java
new file mode 100644
index 0000000..9e1032c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing;
+
+
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.tools.FileObject;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static java.util.Optional.empty;
+import static java.util.Optional.ofNullable;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.warn;
+
+/**
+ * A storage class for metadata under class path
+ */
+public class ClassPathMetadataStorage {
+
+ private final Filer filer;
+
+ public ClassPathMetadataStorage(ProcessingEnvironment processingEnv) {
+ this.filer = processingEnv.getFiler();
+ }
+
+ public void write(Supplier<String> contentSupplier, String resourceName) {
+ try (Writer writer = getWriter(resourceName)) {
+ writer.write(contentSupplier.get());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public <T> Optional<T> read(String resourceName, Function<Reader, T> consumer) {
+ if (exists(resourceName)) {
+ try (Reader reader = getReader(resourceName)) {
+ return ofNullable(consumer.apply(reader));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return empty();
+ }
+
+ private boolean exists(String resourceName) {
+
+ return getResource(resourceName)
+ .map(FileObject::toUri)
+ .map(File::new)
+ .map(File::exists)
+ .orElse(false);
+ }
+
+ private Reader getReader(String resourceName) {
+ return getResource(resourceName).map(fileObject -> {
+ try {
+ return fileObject.openReader(false);
+ } catch (IOException e) {
+ }
+ return null;
+ }).orElse(null);
+ }
+
+ private FileObject createResource(String resourceName) throws IOException {
+ return filer.createResource(CLASS_OUTPUT, "", resourceName);
+ }
+
+ private Optional<FileObject> getResource(String resourceName) {
+ try {
+ FileObject fileObject = filer.getResource(CLASS_OUTPUT, "", resourceName);
+ return ofNullable(fileObject);
+ } catch (IOException e) {
+ warn(e.getMessage());
+ }
+ return empty();
+ }
+
+ private Writer getWriter(String resourceName) throws IOException {
+ FileObject fileObject = createResource(resourceName);
+ info("The resource[path : %s , deleted : %s] will be written", fileObject.toUri().getPath(), fileObject.delete());
+ return fileObject.openWriter();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.java
new file mode 100644
index 0000000..837cdec
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing;
+
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+
+import com.google.gson.Gson;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.typesIn;
+import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
+
+/**
+ * The {@link Processor} class to generate the metadata of {@link ServiceDefinition} whose classes are annotated by Dubbo's @Service
+ *
+ * @see Processor
+ * @since 2.7.5
+ */
+public class ServiceDefinitionMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
+
+ private List<ServiceDefinition> serviceDefinitions = new LinkedList<>();
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+ typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
+
+ if (roundEnv.processingOver()) {
+ ClassPathMetadataStorage writer = new ClassPathMetadataStorage(processingEnv);
+ writer.write(() -> new Gson().toJson(serviceDefinitions), "META-INF/dubbo/service-definitions.json");
+ }
+
+ return false;
+ }
+
+ private void process(ProcessingEnvironment processingEnv, TypeElement serviceType, Set<? extends TypeElement> annotations) {
+ serviceDefinitions.add(build(processingEnv, serviceType));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java
new file mode 100644
index 0000000..d7ebc3a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeMirror;
+import java.lang.reflect.Array;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Array}
+ *
+ * @since 2.7.5
+ */
+public class ArrayTypeDefinitionBuilder implements TypeDefinitionBuilder<ArrayType> {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+ return isArrayType(type);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, ArrayType type, TypeDefinition typeDefinition) {
+ TypeMirror componentType = type.getComponentType();
+ typeDefinition.getItems().add(TypeDefinitionBuilder.build(processingEnv, componentType));
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 4;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.java
new file mode 100644
index 0000000..3ed2b45
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Collection}
+ *
+ * @since 2.7.5
+ */
+public class CollectionTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+ Elements elements = processingEnv.getElementUtils();
+ TypeElement collectionTypeElement = elements.getTypeElement(Collection.class.getTypeName());
+ TypeMirror collectionType = collectionTypeElement.asType();
+ Types types = processingEnv.getTypeUtils();
+ TypeMirror erasedType = types.erasure(type);
+ return types.isAssignable(erasedType, collectionType);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+ // Generic Type arguments
+ type.getTypeArguments()
+ .stream()
+ .map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
+ .filter(Objects::nonNull)
+ .forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 5;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.java
new file mode 100644
index 0000000..b12dcef
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+
+/**
+ * An interface of {@link TypeDefinitionBuilder} for {@link DeclaredType}
+ *
+ * @since 2.7.5
+ */
+public interface DeclaredTypeDefinitionBuilder extends TypeDefinitionBuilder<DeclaredType> {
+
+ @Override
+ default boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ if (declaredType == null) {
+ return false;
+ }
+ return accept(processingEnv, declaredType);
+ }
+
+ /**
+ * Test the specified {@link DeclaredType type} is accepted or not
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param type {@link DeclaredType type}
+ * @return <code>true</code> if accepted
+ */
+ boolean accept(ProcessingEnvironment processingEnv, DeclaredType type);
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.java
new file mode 100644
index 0000000..c0ed002
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.util.FieldUtils;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Enum}
+ *
+ * @since 2.7.5
+ */
+public class EnumTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+ return isEnumType(type);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+ getDeclaredFields(type, FieldUtils::isEnumMemberField)
+ .stream()
+ .map(Element::getSimpleName)
+ .map(Name::toString)
+ .forEach(typeDefinition.getEnums()::add);
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 2;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java
new file mode 100644
index 0000000..f9c648c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
+
+/**
+ * {@link TypeDefinitionBuilder} for General Object
+ *
+ * @since 2.7.5
+ */
+public class GeneralTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+ return isClassType(type);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+
+ String typeName = type.toString();
+
+ TypeElement typeElement = getType(processingEnv, typeName);
+
+ buildProperties(processingEnv, typeElement, typeDefinition);
+ }
+
+ protected void buildProperties(ProcessingEnvironment processingEnv, TypeElement type, TypeDefinition definition) {
+ getNonStaticFields(type).forEach(field -> {
+ String fieldName = field.getSimpleName().toString();
+ TypeDefinition propertyType = TypeDefinitionBuilder.build(processingEnv, field);
+ if (propertyType != null) {
+ definition.getProperties().put(fieldName, propertyType);
+ }
+ });
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.java
new file mode 100644
index 0000000..a0a204d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Map}
+ *
+ * @since 2.7.5
+ */
+public class MapTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+ Elements elements = processingEnv.getElementUtils();
+ TypeElement mapTypeElement = elements.getTypeElement(Map.class.getTypeName());
+ TypeMirror mapType = mapTypeElement.asType();
+ Types types = processingEnv.getTypeUtils();
+ TypeMirror erasedType = types.erasure(type);
+ return types.isAssignable(erasedType, mapType);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+ // Generic Type arguments
+ type.getTypeArguments()
+ .stream()
+ .map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
+ .filter(Objects::nonNull)
+ .forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
+
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 6;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java
new file mode 100644
index 0000000..c2bad78
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getReturnType;
+
+/**
+ * A Builder class for {@link MethodDefinition}
+ *
+ * @see MethodDefinition
+ * @since 2.7.5
+ */
+public interface MethodDefinitionBuilder {
+
+ static MethodDefinition build(ProcessingEnvironment processingEnv, ExecutableElement method) {
+ MethodDefinition methodDefinition = new MethodDefinition();
+ methodDefinition.setName(getMethodName(method));
+ methodDefinition.setReturnType(getReturnType(method));
+ methodDefinition.setParameterTypes(getMethodParameterTypes(method));
+ methodDefinition.setParameters(getMethodParameters(processingEnv, method));
+ return methodDefinition;
+ }
+
+ static List<TypeDefinition> getMethodParameters(ProcessingEnvironment processingEnv, ExecutableElement method) {
+ return method.getParameters().stream()
+ .map(element -> TypeDefinitionBuilder.build(processingEnv, element))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java
new file mode 100644
index 0000000..903c15f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link PrimitiveType primitve type}
+ *
+ * @since 2.7.5
+ */
+public class PrimitiveTypeDefinitionBuilder implements TypeDefinitionBuilder<PrimitiveType> {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+ return isPrimitiveType(type);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, PrimitiveType type, TypeDefinition typeDefinition) {
+ // DO NOTHING
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 3;
+ }
+}
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java
new file mode 100644
index 0000000..8563e00
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
+
+/**
+ * A Builder for {@link ServiceDefinition}
+ *
+ * @see ServiceDefinition
+ * @since 2.7.5
+ */
+public interface ServiceDefinitionBuilder {
+
+ static ServiceDefinition build(ProcessingEnvironment processingEnv, TypeElement type) {
+ ServiceDefinition serviceDefinition = new ServiceDefinition();
+ serviceDefinition.setCanonicalName(type.toString());
+ serviceDefinition.setCodeSource(getResourceName(type.toString()));
+
+ // Get all super types and interface excluding the specified type
+ // and then the result will be added into ServiceDefinition#getTypes()
+ getHierarchicalTypes(type.asType(), Object.class)
+ .stream()
+ .map(t -> TypeDefinitionBuilder.build(processingEnv, t))
+ .forEach(serviceDefinition.getTypes()::add);
+
+ // Get all declared methods that will be added into ServiceDefinition#getMethods()
+ getPublicNonStaticMethods(type, Object.class)
+ .stream()
+ .map(method -> MethodDefinitionBuilder.build(processingEnv, method))
+ .forEach(serviceDefinition.getMethods()::add);
+
+ return serviceDefinition;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.java
new file mode 100644
index 0000000..634d7be
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.util.TypeUtils;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
+
+
+/**
+ * {@link TypeDefinitionBuilder} for {@link TypeUtils#SIMPLE_TYPES Java Simple Type}
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+ @Override
+ public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+ return isSimpleType(type);
+ }
+
+ @Override
+ public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+ // DO NOTHING
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY - 1;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java
new file mode 100644
index 0000000..415754b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
+
+/**
+ * A class builds the instance of {@link TypeDefinition}
+ *
+ * @since 2.7.5
+ */
+public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized {
+
+ /**
+ * Test the specified {@link TypeMirror type} is accepted or not
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param type {@link TypeMirror type}
+ * @return <code>true</code> if accepted
+ */
+ boolean accept(ProcessingEnvironment processingEnv, TypeMirror type);
+
+ /**
+ * Build the instance of {@link TypeDefinition}
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param type {@link T type}
+ * @param typeDefinition {@link TypeDefinition} to be built
+ * @return an instance of {@link TypeDefinition}
+ */
+ void build(ProcessingEnvironment processingEnv, T type, TypeDefinition typeDefinition);
+
+ /**
+ * Build the instance of {@link TypeDefinition} from the specified {@link Element element}
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param element {@link Element source element}
+ * @return non-null
+ */
+ static TypeDefinition build(ProcessingEnvironment processingEnv, Element element) {
+ TypeDefinition typeDefinition = build(processingEnv, element.asType());
+ typeDefinition.set$ref(element.toString());
+ return typeDefinition;
+ }
+
+ /**
+ * Build the instance of {@link TypeDefinition} from the specified {@link TypeMirror type}
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param type {@link TypeMirror type}
+ * @return non-null
+ */
+ static TypeDefinition build(ProcessingEnvironment processingEnv, TypeMirror type) {
+ String typeName = type.toString();
+ TypeDefinition typeDefinition = new TypeDefinition(typeName);
+
+ // Build by all instances of TypeDefinitionBuilder that were loaded By Java SPI
+ load(TypeDefinitionBuilder.class, TypeDefinitionBuilder.class.getClassLoader())
+ .filter(builder -> builder.accept(processingEnv, type))
+ .findFirst()
+ .ifPresent(builder -> {
+ builder.build(processingEnv, type, typeDefinition);
+ // typeDefinition.setTypeBuilderName(builder.getClass().getName());
+ });
+
+ return typeDefinition;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..51ef786
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractAnnotatedMethodParameterProcessor implements AnnotatedMethodParameterProcessor {
+
+ @Override
+ public final void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ String annotationValue = getAnnotationValue(annotation, parameter, parameterIndex);
+ String defaultValue = getDefaultValue(annotation, parameter, parameterIndex);
+ process(annotationValue, defaultValue, annotation, parameter, parameterIndex, method, restMethodMetadata);
+ }
+
+ protected abstract void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
+ ExecutableElement method, RestMethodMetadata restMethodMetadata);
+
+ protected String getAnnotationValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+ return getValue(annotation);
+ }
+
+ protected String getDefaultValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+ return buildDefaultValue(parameterIndex);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..36fee79
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static java.lang.ThreadLocal.withInitial;
+import static java.util.Collections.emptyList;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
+import static org.apache.dubbo.metadata.annotation.processing.builder.MethodDefinitionBuilder.build;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getGroup;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getVersion;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.resolveServiceInterfaceName;
+
+/**
+ * Abstract {@link ServiceRestMetadataProcessor} implementation
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractServiceRestMetadataProcessor implements ServiceRestMetadataProcessor {
+
+ private final static ThreadLocal<Map<String, Object>> threadLocalCache = withInitial(HashMap::new);
+
+ private final static Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = loadAnnotatedMethodParameterProcessors();
+
+ private final String processorName = getClass().getSimpleName();
+
+ @Override
+ public final ServiceRestMetadata process(ProcessingEnvironment processingEnv,
+ TypeElement serviceType,
+ Set<? extends TypeElement> annotations) {
+
+ info("%s is processing the service type[%s] with annotations[%s]", processorName, serviceType,
+ annotations.stream().map(t -> "@" + t.toString()).collect(Collectors.joining(",")));
+
+ ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata();
+
+ try {
+ AnnotationMirror serviceAnnotation = getAnnotation(serviceType);
+ serviceRestMetadata.setServiceInterface(resolveServiceInterfaceName(serviceType, serviceAnnotation));
+ serviceRestMetadata.setGroup(getGroup(serviceAnnotation));
+ serviceRestMetadata.setVersion(getVersion(serviceAnnotation));
+
+ List<? extends ExecutableElement> methods = getPublicNonStaticMethods(serviceType, Object.class);
+
+ methods.forEach(method -> {
+ processRestMethodMetadata(processingEnv, serviceType, method)
+ .ifPresent(serviceRestMetadata.getMeta()::add);
+ });
+ } finally {
+ clearCache();
+ }
+
+ info("The %s's process result : %s", processorName, serviceRestMetadata);
+
+ return serviceRestMetadata;
+ }
+
+ protected Optional<RestMethodMetadata> processRestMethodMetadata(ProcessingEnvironment processingEnv,
+ TypeElement serviceType, ExecutableElement method) {
+
+ String requestPath = getRequestPath(processingEnv, serviceType, method); // requestPath is required
+
+ if (requestPath == null) {
+ return empty();
+ }
+
+ String requestMethod = getRequestMethod(processingEnv, serviceType, method); // requestMethod is required
+
+ if (requestMethod == null) {
+ return empty();
+ }
+
+ RestMethodMetadata metadata = new RestMethodMetadata();
+
+ MethodDefinition methodDefinition = getMethodDefinition(processingEnv, serviceType, method);
+ // Set MethodDefinition
+ metadata.setMethod(methodDefinition);
+
+ // process the annotated method parameters
+ processAnnotatedMethodParameters(method, serviceType, metadata);
+
+ // process produces
+ Set<String> produces = new LinkedHashSet<>();
+ processProduces(processingEnv, serviceType, method, produces);
+
+ // process consumes
+ Set<String> consumes = new LinkedHashSet<>();
+ processConsumes(processingEnv, serviceType, method, consumes);
+
+ // Initialize RequestMetadata
+ RequestMetadata request = metadata.getRequest();
+ request.setPath(requestPath);
+ request.setMethod(requestMethod);
+ request.setProduces(produces);
+ request.setConsumes(consumes);
+
+ // Post-Process
+ postProcessRestMethodMetadata(processingEnv, serviceType, method, metadata);
+
+ return of(metadata);
+ }
+
+ /**
+ * Post-Process for {@link RestMethodMetadata}, sub-type could override this method for further works
+ *
+ * @param processingEnv {@link ProcessingEnvironment}
+ * @param serviceType The type that @Service annotated
+ * @param method The public method of <code>serviceType</code>
+ * @param metadata {@link RestMethodMetadata} maybe updated
+ */
+ protected void postProcessRestMethodMetadata(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, RestMethodMetadata metadata) {
+ }
+
+ protected abstract String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method);
+
+ protected abstract String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method);
+
+ protected MethodDefinition getMethodDefinition(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method) {
+ return build(processingEnv, method);
+ }
+
+ protected void processAnnotatedMethodParameters(ExecutableElement method, TypeElement type,
+ RestMethodMetadata metadata) {
+ List<? extends VariableElement> methodParameters = method.getParameters();
+ int size = methodParameters.size();
+ for (int i = 0; i < size; i++) {
+ VariableElement parameter = methodParameters.get(i);
+ // Add indexed parameter name
+ metadata.addIndexToName(i, parameter.getSimpleName().toString());
+ processAnnotatedMethodParameter(parameter, i, method, type, metadata);
+ }
+ }
+
+ protected void processAnnotatedMethodParameter(VariableElement parameter, int parameterIndex,
+ ExecutableElement method, TypeElement serviceType,
+ RestMethodMetadata metadata) {
+
+ parameter.getAnnotationMirrors().forEach(annotation -> {
+ String annotationType = annotation.getAnnotationType().toString();
+ parameterProcessorsMap.getOrDefault(annotationType, emptyList())
+ .forEach(parameterProcessor -> {
+ parameterProcessor.process(annotation, parameter, parameterIndex, method, metadata);
+ });
+ });
+ }
+
+ protected abstract void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> produces);
+
+ protected abstract void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> consumes);
+
+ protected static final void put(String name, Object value) {
+ Map<String, Object> cache = getCache();
+ cache.put(name, value);
+ }
+
+ protected static final <T> T get(String name) throws ClassCastException {
+ Map<String, Object> cache = getCache();
+ return (T) cache.get(name);
+ }
+
+ protected static final <V> V computeIfAbsent(String name, Function<? super String, ? extends V> mappingFunction) {
+ return (V) getCache().computeIfAbsent(name, mappingFunction);
+ }
+
+ private static Map<String, List<AnnotatedMethodParameterProcessor>> loadAnnotatedMethodParameterProcessors() {
+ Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = new LinkedHashMap<>();
+
+ load(AnnotatedMethodParameterProcessor.class, AnnotatedMethodParameterProcessor.class.getClassLoader())
+ .forEach(processor -> {
+ List<AnnotatedMethodParameterProcessor> processors =
+ parameterProcessorsMap.computeIfAbsent(processor.getAnnotationType(), k -> new LinkedList<>());
+ processors.add(processor);
+ });
+
+ return parameterProcessorsMap;
+ }
+
+ private static Map<String, Object> getCache() {
+ return threadLocalCache.get();
+ }
+
+ private static void clearCache() {
+ Map<String, Object> cache = getCache();
+ cache.clear();
+ threadLocalCache.remove();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..523f932
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The interface to process the parameter of method that was annotated
+ *
+ * @since 2.7.5
+ */
+public interface AnnotatedMethodParameterProcessor extends Prioritized {
+
+ /**
+ * The string presenting the annotation type
+ *
+ * @return non-null
+ */
+ String getAnnotationType();
+
+ /**
+ * Process the specified method {@link VariableElement parameter}
+ *
+ * @param annotation {@link AnnotationMirror the target annotation} whose type is {@link #getAnnotationType()}
+ * @param parameter {@link VariableElement method parameter}
+ * @param parameterIndex the index of parameter in the method
+ * @param method {@link ExecutableElement method that parameter belongs to}
+ * @param restMethodMetadata {@link RestMethodMetadata the metadata is used to update}
+ */
+ void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method,
+ RestMethodMetadata restMethodMetadata);
+
+
+ /**
+ * Build the default value
+ *
+ * @param parameterIndex the index of parameter
+ * @return the placeholder
+ */
+ static String buildDefaultValue(int parameterIndex) {
+ return "{" + parameterIndex + "}";
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..73772db
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * The default implementation of {@link ServiceRestMetadataProcessor}
+ *
+ * @since 2.7.5
+ */
+public class DefaultServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+ @Override
+ public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+ return true;
+ }
+
+ @Override
+ protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method) {
+ return null;
+ }
+
+ @Override
+ protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method) {
+ return null;
+ }
+
+ @Override
+ protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> produces) {
+
+ }
+
+ @Override
+ protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> consumes) {
+
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java
new file mode 100644
index 0000000..5c1a400
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractServiceAnnotationProcessor;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.typesIn;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.isServiceAnnotationPresent;
+
+/**
+ * The {@link Processor} class to generate the metadata of REST from the classes that are annotated by Dubbo's
+ *
+ * @Service
+ * @see Processor
+ * @since 2.7.5
+ */
+public class ServiceRestMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
+
+ private List<ServiceRestMetadataProcessor> metadataProcessors;
+
+ private ServiceRestMetadataStorage serviceRestMetadataWriter;
+
+ private Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ this.metadataProcessors = loadServices(ServiceRestMetadataProcessor.class, getClass().getClassLoader());
+ this.serviceRestMetadataWriter = new ServiceRestMetadataStorage(processingEnv);
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+ typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
+
+ if (roundEnv.processingOver()) {
+ try {
+ serviceRestMetadataWriter.append(serviceRestMetadata);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ return false;
+ }
+
+ private void process(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ Set<? extends TypeElement> annotations) {
+ metadataProcessors
+ .stream()
+ .filter(processor -> supports(processor, processingEnv, serviceType))
+ .map(processor -> processor.process(processingEnv, serviceType, annotations))
+ .forEach(serviceRestMetadata::add);
+ }
+
+ private boolean supports(ServiceRestMetadataProcessor processor, ProcessingEnvironment processingEnv,
+ TypeElement serviceType) {
+ // @Service must be present in service type
+ return isServiceAnnotationPresent(serviceType) && processor.supports(processingEnv, serviceType);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..8e2af64
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * The class to process {@link ServiceRestMetadata} based on Annotation Processor Tool
+ *
+ * @since 2.7.5
+ */
+public interface ServiceRestMetadataProcessor extends Prioritized {
+
+ /**
+ * Supports or not to the specified service type
+ *
+ * @param processingEnvironment {@link ProcessingEnvironment}
+ * @param serviceType Dubbo service type or interface
+ * @return if supports, return <code>true</code>, or <code>false</code>
+ */
+ boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType);
+
+ /**
+ * Process the {@link ServiceRestMetadata} from given service type
+ *
+ * @param processingEnvironment {@link ProcessingEnvironment}
+ * @param serviceType Dubbo service type or interface
+ * @param annotations
+ * @return non-null
+ */
+ ServiceRestMetadata process(ProcessingEnvironment processingEnvironment,
+ TypeElement serviceType,
+ Set<? extends TypeElement> annotations);
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.java
new file mode 100644
index 0000000..7365363
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.annotation.processing.ClassPathMetadataStorage;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import com.google.gson.Gson;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.gson.reflect.TypeToken.getParameterized;
+
+/**
+ * The storage for {@link ServiceRestMetadata}
+ */
+public class ServiceRestMetadataStorage {
+
+ public static final String METADATA_RESOURCE_PATH = "META-INF/dubbo/service-rest-metadata.json";
+
+ private final ClassPathMetadataStorage storage;
+
+ public ServiceRestMetadataStorage(ProcessingEnvironment processingEnv) {
+ this.storage = new ClassPathMetadataStorage(processingEnv);
+ }
+
+ public void append(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
+ Set<ServiceRestMetadata> allServiceRestMetadata = new LinkedHashSet<>();
+ storage.read(METADATA_RESOURCE_PATH, reader -> {
+ Gson gson = new Gson();
+ return (List) gson.fromJson(reader, getParameterized(List.class, ServiceRestMetadata.class).getType());
+ }).ifPresent(existedMetadata -> {
+ // Add all existed ServiceRestMetadata
+ allServiceRestMetadata.addAll(existedMetadata);
+ });
+ // Add all new ServiceRestMetadata
+ allServiceRestMetadata.addAll(serviceRestMetadata);
+ write(serviceRestMetadata);
+ }
+
+ public void write(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
+ if (serviceRestMetadata.isEmpty()) {
+ return;
+ }
+ storage.write(() -> new Gson().toJson(serviceRestMetadata), METADATA_RESOURCE_PATH);
+ }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.java
new file mode 100644
index 0000000..0818ff3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @DefaultValue
+ * *
+ *
+ * @since 2.7.5
+ */
+public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+ /**
+ * The annotation class name of @DefaultValue
+ */
+ public static final String DEFAULT_VALUE_ANNOTATION_CLASS_NAME = "javax.ws.rs.DefaultValue";
+
+ @Override
+ public String getAnnotationType() {
+ return DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
+ }
+
+ @Override
+ protected void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+
+ // process the request parameters
+ setDefaultValue(requestMetadata.getParams(), defaultValue, annotationValue);
+ // process the request headers
+ setDefaultValue(requestMetadata.getHeaders(), defaultValue, annotationValue);
+
+ }
+
+ private void setDefaultValue(Map<String, List<String>> source, String placeholderValue, String defaultValue) {
+ OUTTER:
+ for (Map.Entry<String, List<String>> entry : source.entrySet()) {
+ List<String> values = entry.getValue();
+ int size = values.size();
+ for (int i = 0; i < size; i++) {
+ String value = values.get(i);
+ if (placeholderValue.equals(value)) {
+ values.set(i, defaultValue);
+ break OUTTER;
+ }
+ }
+ }
+ }
+
+ public int getPriority() {
+ return MIN_PRIORITY;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
index b3b27e6..c323e8a 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
@@ -14,27 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
/**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @FormParam
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class FormParamParameterProcessor extends ParamAnnotationParameterProcessor {
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ @Override
+ public String getAnnotationType() {
+ return "javax.ws.rs.FormParam";
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java
new file mode 100644
index 0000000..278cf93
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @HeaderParam
+ *
+ * @since 2.7.5
+ */
+public class HeaderParamParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+ @Override
+ public String getAnnotationType() {
+ return "javax.ws.rs.HeaderParam";
+ }
+
+ @Override
+ protected void process(String headerName, String defaultValue, AnnotationMirror annotation,
+ VariableElement parameter, int parameterIndex,
+ ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+ // Add the placeholder as header value
+ requestMetadata.addHeader(headerName, buildDefaultValue(parameterIndex));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..564760f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.AnnotatedConstruct;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
+
+/**
+ * {@link ServiceRestMetadataProcessor} implementation for JAX-RS 2 and 1
+ *
+ * @since 2.7.5
+ */
+public class JAXRSServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+ /**
+ * The annotation name of @Path
+ */
+ public static final String PATH_ANNOTATION_CLASS_NAME = "javax.ws.rs.Path";
+
+ /**
+ * The annotation name of @HttpMethod
+ */
+ public static final String HTTP_METHOD_ANNOTATION_CLASS_NAME = "javax.ws.rs.HttpMethod";
+
+ /**
+ * The annotation class name of @Produces
+ */
+ public static final String PRODUCES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Produces";
+
+ /**
+ * The annotation class name of @Consumes
+ */
+ public static final String CONSUMES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Consumes";
+
+ @Override
+ public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+ return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
+ }
+
+ @Override
+ protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
+ String pathFromType = getPathValue(processingEnv, serviceType);
+ String pathFromMethod = getPathValue(method);
+ return buildPath(pathFromType, pathFromMethod);
+ }
+
+ @Override
+ protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
+ AnnotationMirror annotation = findMetaAnnotation(method, HTTP_METHOD_ANNOTATION_CLASS_NAME);
+ return getValue(annotation);
+ }
+
+ @Override
+ protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> produces) {
+ addAnnotationValues(method, PRODUCES_ANNOTATION_CLASS_NAME, produces);
+ }
+
+ @Override
+ protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> consumes) {
+ addAnnotationValues(method, CONSUMES_ANNOTATION_CLASS_NAME, consumes);
+ }
+
+
+ private void addAnnotationValues(Element element, String annotationAttributeName, Set<String> result) {
+ AnnotationMirror annotation = findAnnotation(element, annotationAttributeName);
+ String[] value = getValue(annotation);
+ if (value != null) {
+ Stream.of(value).forEach(result::add);
+ }
+ }
+
+ private String getPathValue(ProcessingEnvironment processingEnv, TypeElement serviceType) {
+ AnnotationMirror annotation = findAnnotation(serviceType, PATH_ANNOTATION_CLASS_NAME);
+ return getValue(annotation);
+ }
+
+ private String getPathValue(AnnotatedConstruct annotatedConstruct) {
+ AnnotationMirror annotation = getAnnotation(annotatedConstruct, PATH_ANNOTATION_CLASS_NAME);
+ return getValue(annotation);
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
index b3b27e6..026b648 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
@@ -14,27 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
/**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @MatrixParam
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class MatrixParamParameterProcessor extends ParamAnnotationParameterProcessor {
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ @Override
+ public String getAnnotationType() {
+ return "javax.ws.rs.MatrixParam";
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/ParamAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/ParamAnnotationParameterProcessor.java
new file mode 100644
index 0000000..d615cdc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/ParamAnnotationParameterProcessor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @*Param
+ */
+public abstract class ParamAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+ protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
+ ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+ requestMetadata.addParam(name, defaultValue);
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
index b3b27e6..42e14ab 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
@@ -14,27 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
/**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @QueryParam
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class QueryParamParameterProcessor extends ParamAnnotationParameterProcessor {
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ @Override
+ public String getAnnotationType() {
+ return "javax.ws.rs.QueryParam";
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
new file mode 100644
index 0000000..1fa5285
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @Request*
+ */
+public abstract class AbstractRequestAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+
+ protected abstract void process(String name, String defaultValue, AnnotationMirror annotation,
+ VariableElement parameter, int parameterIndex,
+ ExecutableElement method,
+ RestMethodMetadata restMethodMetadata);
+
+ @Override
+ protected String getAnnotationValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+ // try to get "value" attribute first
+ String name = super.getAnnotationValue(annotation, parameter, parameterIndex);
+
+ // try to get "name" attribute if required
+ if (isEmpty(name)) {
+ name = getAttribute(annotation, "name");
+ }
+
+ // finally , try to the name of parameter
+ if (isEmpty(name)) {
+ name = parameter.getSimpleName().toString();
+ }
+
+ return name;
+ }
+
+ protected String getDefaultValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+ String defaultValue = getAttribute(annotation, "defaultValue");
+ if (isEmpty(defaultValue)) {
+ defaultValue = super.getDefaultValue(annotation, parameter, parameterIndex);
+ }
+ return defaultValue;
+ }
+
+ protected boolean isEmpty(String str) {
+ return str == null || str.isEmpty();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java
new file mode 100644
index 0000000..94929bc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestHeader
+ */
+public class RequestHeaderParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+ @Override
+ public String getAnnotationType() {
+ return "org.springframework.web.bind.annotation.RequestHeader";
+ }
+
+ @Override
+ protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ restMethodMetadata.getRequest().addHeader(name, defaultValue);
+ }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.java
new file mode 100644
index 0000000..1292025
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestParam
+ */
+public class RequestParamParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+ @Override
+ public String getAnnotationType() {
+ return "org.springframework.web.bind.annotation.RequestParam";
+ }
+
+ @Override
+ protected void process(String name, String defaultValue, AnnotationMirror annotation,
+ VariableElement parameter, int parameterIndex,
+ ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+ restMethodMetadata.getRequest().addParam(name, defaultValue);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..b9f7009
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import java.lang.reflect.Array;
+import java.util.Set;
+
+import static java.lang.String.valueOf;
+import static java.lang.reflect.Array.getLength;
+import static java.util.stream.Stream.of;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
+import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAllAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
+
+/**
+ * {@link ServiceRestMetadataProcessor}
+ *
+ * @since 2.7.5
+ */
+public class SpringMvcServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+ private static final int FIRST_ELEMENT_INDEX = 0;
+
+ public static final String CONTROLLER_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Controller";
+
+ public static final String REQUEST_MAPPING_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestMapping";
+
+ @Override
+ public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+ return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
+ }
+
+ @Override
+ protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method) {
+
+ String requestPathFromType = getRequestPath(serviceType);
+
+ String requestPathFromMethod = getRequestPath(method);
+
+ return buildPath(requestPathFromType, requestPathFromMethod);
+ }
+
+
+ @Override
+ protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method) {
+
+ AnnotationMirror requestMapping = getRequestMapping(method);
+
+ // httpMethod is an array of RequestMethod
+ Object httpMethod = getAttribute(requestMapping, "method");
+
+ if (httpMethod == null || getLength(httpMethod) < 1) {
+ return null;
+ }
+
+ // TODO Is is required to support more request methods?
+ return valueOf(Array.get(httpMethod, FIRST_ELEMENT_INDEX));
+ }
+
+ private AnnotationMirror getRequestMapping(Element element) {
+ // try "@RequestMapping" first
+ AnnotationMirror requestMapping = findAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+ // try the annotation meta-annotated later
+ if (requestMapping == null) {
+ requestMapping = findMetaAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+ }
+ return requestMapping;
+ }
+
+ @Override
+ protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> produces) {
+ addMediaTypes(method, "produces", produces);
+ }
+
+ @Override
+ protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+ ExecutableElement method, Set<String> consumes) {
+ addMediaTypes(method, "consumes", consumes);
+ }
+
+ private void addMediaTypes(ExecutableElement method, String annotationAttributeName, Set<String> mediaTypesSet) {
+
+ AnnotationMirror mappingAnnotation = getMappingAnnotation(method);
+
+ String[] mediaTypes = getAttribute(mappingAnnotation, annotationAttributeName);
+
+ if (isNotEmpty(mediaTypes)) {
+ of(mediaTypes).forEach(mediaTypesSet::add);
+ }
+ }
+
+ private AnnotationMirror getMappingAnnotation(Element element) {
+ return computeIfAbsent(valueOf(element), key ->
+ filterFirst(getAllAnnotations(element), annotation -> {
+ DeclaredType annotationType = annotation.getAnnotationType();
+ // try "@RequestMapping" first
+ if (REQUEST_MAPPING_ANNOTATION_CLASS_NAME.equals(annotationType.toString())) {
+ return true;
+ }
+ // try meta annotation
+ return isAnnotationPresent(annotationType.asElement(), REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+ })
+ );
+ }
+
+ private String getRequestPath(Element element) {
+ AnnotationMirror mappingAnnotation = getMappingAnnotation(element);
+ return getRequestPath(mappingAnnotation);
+ }
+
+ private String getRequestPath(AnnotationMirror mappingAnnotation) {
+ // try "value" first
+ String[] value = getAttribute(mappingAnnotation, "value");
+
+ if (isEmpty(value)) { // try "path" later
+ value = getAttribute(mappingAnnotation, "path");
+ }
+
+ if (isEmpty(value)) {
+ return "";
+ }
+ // TODO Is is required to support more request paths?
+ return value[FIRST_ELEMENT_INDEX];
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java
new file mode 100644
index 0000000..ac3877d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.AnnotatedConstruct;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeMirror;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.lang.Enum.valueOf;
+import static java.util.Collections.emptyList;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSameType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isTypeElement;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+
+/**
+ * The utilities class for annotation in the package "javax.lang.model.*"
+ *
+ * @since 2.7.5
+ */
+public interface AnnotationUtils {
+
+ static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct,
+ Class<? extends Annotation> annotationClass) {
+ return annotationClass == null ?
+ null :
+ getAnnotation(annotatedConstruct, annotationClass.getTypeName());
+ }
+
+ static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) {
+ List<AnnotationMirror> annotations = getAnnotations(annotatedConstruct, annotationClassName);
+ return annotations.isEmpty() ? null : annotations.get(0);
+ }
+
+ static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct, Class<? extends Annotation> annotationClass) {
+ return annotationClass == null ?
+ emptyList() :
+ getAnnotations(annotatedConstruct, annotationClass.getTypeName());
+ }
+
+ static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
+ CharSequence annotationClassName) {
+ return getAnnotations(annotatedConstruct,
+ annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
+ }
+
+ static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct) {
+ return getAnnotations(annotatedConstruct, EMPTY_ARRAY);
+ }
+
+ static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
+ Predicate<AnnotationMirror>... annotationFilters) {
+
+ AnnotatedConstruct actualAnnotatedConstruct = annotatedConstruct;
+
+ if (annotatedConstruct instanceof TypeMirror) {
+ actualAnnotatedConstruct = ofTypeElement((TypeMirror) actualAnnotatedConstruct);
+ }
+
+ return actualAnnotatedConstruct == null ?
+ emptyList() :
+ filterAll((List<AnnotationMirror>) actualAnnotatedConstruct.getAnnotationMirrors(), annotationFilters);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(TypeMirror type) {
+ return getAllAnnotations(ofTypeElement(type));
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(Element element) {
+ return getAllAnnotations(element, EMPTY_ARRAY);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Class<? extends Annotation> annotationClass) {
+ return getAllAnnotations(ofTypeElement(type), annotationClass);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(Element element, Class<? extends Annotation> annotationClass) {
+ return element == null || annotationClass == null ?
+ emptyList() :
+ getAllAnnotations(element, annotationClass.getTypeName());
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(TypeMirror type, CharSequence annotationClassName) {
+ return getAllAnnotations(ofTypeElement(type), annotationClassName);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(Element element, CharSequence annotationClassName) {
+ return getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Predicate<AnnotationMirror>... annotationFilters) {
+ return getAllAnnotations(ofTypeElement(type), annotationFilters);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(Element element, Predicate<AnnotationMirror>... annotationFilters) {
+
+ List<AnnotationMirror> allAnnotations = isTypeElement(element) ?
+ getHierarchicalTypes(ofTypeElement(element))
+ .stream()
+ .map(AnnotationUtils::getAnnotations)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList()) :
+ element == null ? emptyList() : (List<AnnotationMirror>) element.getAnnotationMirrors();
+
+ return filterAll(allAnnotations, annotationFilters);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType) {
+ return getAllAnnotations(processingEnv, annotatedType, EMPTY_ARRAY);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType,
+ Predicate<AnnotationMirror>... annotationFilters) {
+ return annotatedType == null ?
+ emptyList() :
+ getAllAnnotations(processingEnv, annotatedType.getTypeName(), annotationFilters);
+ }
+
+ static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, CharSequence annotatedTypeName,
+ Predicate<AnnotationMirror>... annotationFilters) {
+ return getAllAnnotations(getType(processingEnv, annotatedTypeName), annotationFilters);
+ }
+
+ static AnnotationMirror findAnnotation(TypeMirror type, Class<? extends Annotation> annotationClass) {
+ return annotationClass == null ? null : findAnnotation(type, annotationClass.getTypeName());
+ }
+
+ static AnnotationMirror findAnnotation(TypeMirror type, CharSequence annotationClassName) {
+ return findAnnotation(ofTypeElement(type), annotationClassName);
+ }
+
+ static AnnotationMirror findAnnotation(Element element, Class<? extends Annotation> annotationClass) {
+ return annotationClass == null ? null : findAnnotation(element, annotationClass.getTypeName());
+ }
+
+ static AnnotationMirror findAnnotation(Element element, CharSequence annotationClassName) {
+ return filterFirst(getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName)));
+ }
+
+ static AnnotationMirror findMetaAnnotation(Element annotatedConstruct, CharSequence metaAnnotationClassName) {
+ return annotatedConstruct == null ?
+ null :
+ getAnnotations(annotatedConstruct)
+ .stream()
+ .map(annotation -> findAnnotation(annotation.getAnnotationType(), metaAnnotationClassName))
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElse(null);
+ }
+
+ static boolean isAnnotationPresent(Element element, CharSequence annotationClassName) {
+ return findAnnotation(element, annotationClassName) != null ||
+ findMetaAnnotation(element, annotationClassName) != null;
+ }
+
+ static <T> T getAttribute(AnnotationMirror annotation, String attributeName) {
+ return annotation == null ? null : getAttribute(annotation.getElementValues(), attributeName);
+ }
+
+ static <T> T getAttribute(Map<? extends ExecutableElement, ? extends AnnotationValue> attributesMap,
+ String attributeName) {
+ T annotationValue = null;
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : attributesMap.entrySet()) {
+ ExecutableElement attributeMethod = entry.getKey();
+ if (Objects.equals(attributeName, attributeMethod.getSimpleName().toString())) {
+ TypeMirror attributeType = attributeMethod.getReturnType();
+ AnnotationValue value = entry.getValue();
+ if (attributeType instanceof ArrayType) { // array-typed attribute values
+ ArrayType arrayType = (ArrayType) attributeType;
+ String componentType = arrayType.getComponentType().toString();
+ ClassLoader classLoader = AnnotationUtils.class.getClassLoader();
+ List<AnnotationValue> values = (List<AnnotationValue>) value.getValue();
+ int size = values.size();
+ try {
+ Class componentClass = classLoader.loadClass(componentType);
+ boolean isEnum = componentClass.isEnum();
+ Object array = Array.newInstance(componentClass, values.size());
+ for (int i = 0; i < size; i++) {
+ Object element = values.get(i).getValue();
+ if (isEnum) {
+ element = valueOf(componentClass, element.toString());
+ }
+ Array.set(array, i, element);
+ }
+ annotationValue = (T) array;
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ annotationValue = (T) value.getValue();
+ }
+ break;
+ }
+ }
+ return annotationValue;
+ }
+
+ static <T> T getValue(AnnotationMirror annotation) {
+ return (T) getAttribute(annotation, "value");
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java
new file mode 100644
index 0000000..b6c7346
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.ElementKind.ENUM_CONSTANT;
+import static javax.lang.model.element.ElementKind.FIELD;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.hasModifiers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matches;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+
+/**
+ * The utilities class for the field in the package "javax.lang.model."
+ *
+ * @since 2.7.5
+ */
+public interface FieldUtils {
+
+ static List<VariableElement> getDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
+ return element == null ? emptyList() : getDeclaredFields(element.asType(), fieldFilters);
+ }
+
+ static List<VariableElement> getDeclaredFields(Element element) {
+ return getDeclaredFields(element, EMPTY_ARRAY);
+ }
+
+ static List<VariableElement> getDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
+ return filterAll(fieldsIn(getDeclaredMembers(type)), fieldFilters);
+ }
+
+ static List<VariableElement> getDeclaredFields(TypeMirror type) {
+ return getDeclaredFields(type, EMPTY_ARRAY);
+ }
+
+ static List<VariableElement> getAllDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
+ return element == null ? emptyList() : getAllDeclaredFields(element.asType(), fieldFilters);
+ }
+
+ static List<VariableElement> getAllDeclaredFields(Element element) {
+ return getAllDeclaredFields(element, EMPTY_ARRAY);
+ }
+
+ static List<VariableElement> getAllDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
+ return getHierarchicalTypes(type)
+ .stream()
+ .map(t -> getDeclaredFields(t, fieldFilters))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ static List<VariableElement> getAllDeclaredFields(TypeMirror type) {
+ return getAllDeclaredFields(type, EMPTY_ARRAY);
+ }
+
+ static VariableElement getDeclaredField(Element element, String fieldName) {
+ return element == null ? null : getDeclaredField(element.asType(), fieldName);
+ }
+
+ static VariableElement getDeclaredField(TypeMirror type, String fieldName) {
+ return filterFirst(getDeclaredFields(type, field -> fieldName.equals(field.getSimpleName().toString())));
+ }
+
+ static VariableElement findField(Element element, String fieldName) {
+ return element == null ? null : findField(element.asType(), fieldName);
+ }
+
+ static VariableElement findField(TypeMirror type, String fieldName) {
+ return filterFirst(getAllDeclaredFields(type, field -> equals(field, fieldName)));
+ }
+
+ /**
+ * is Enum's member field or not
+ *
+ * @param field {@link VariableElement} must be public static final fields
+ * @return if field is public static final, return <code>true</code>, or <code>false</code>
+ */
+ static boolean isEnumMemberField(VariableElement field) {
+ if (field == null || !isEnumType(field.getEnclosingElement())) {
+ return false;
+ }
+ return ENUM_CONSTANT.equals(field.getKind());
+ }
+
+ static boolean isNonStaticField(VariableElement field) {
+ return isField(field) && !hasModifiers(field, STATIC);
+ }
+
+ static boolean isField(VariableElement field) {
+ return matches(field, FIELD) || isEnumMemberField(field);
+ }
+
+ static boolean isField(VariableElement field, Modifier... modifiers) {
+ return isField(field) && hasModifiers(field, modifiers);
+ }
+
+ static List<VariableElement> getNonStaticFields(TypeMirror type) {
+ return getDeclaredFields(type, FieldUtils::isNonStaticField);
+ }
+
+ static List<VariableElement> getNonStaticFields(Element element) {
+ return element == null ? emptyList() : getNonStaticFields(element.asType());
+ }
+
+ static List<VariableElement> getAllNonStaticFields(TypeMirror type) {
+ return getAllDeclaredFields(type, FieldUtils::isNonStaticField);
+ }
+
+ static List<VariableElement> getAllNonStaticFields(Element element) {
+ return element == null ? emptyList() : getAllNonStaticFields(element.asType());
+ }
+
+ static boolean equals(VariableElement field, CharSequence fieldName) {
+ return field != null && fieldName != null && field.getSimpleName().toString().equals(fieldName.toString());
+ }
+
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
index b3b27e6..f43ffd9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
@@ -14,27 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.util;
-import org.junit.jupiter.api.Test;
-import java.util.List;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static java.lang.String.format;
/**
- * {@link DubboServiceLoader} Test
+ * Logger Utils
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public interface LoggerUtils {
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ Logger LOGGER = LoggerFactory.getLogger("dubbo-metadata-processor");
+
+ static void info(String format, Object... args) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(format(format, args));
+ }
+ }
+
+ static void warn(String format, Object... args) {
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn(format(format, args));
+ }
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java
new file mode 100644
index 0000000..fc617a1
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+
+/**
+ * The utilities class for the members in the package "javax.lang.model.", such as "field", "method", "constructor"
+ *
+ * @since 2.7.5
+ */
+public interface MemberUtils {
+
+ static boolean matches(Element member, ElementKind kind) {
+ return member == null || kind == null ? false : kind.equals(member.getKind());
+ }
+
+ static boolean isPublicNonStatic(Element member) {
+ return hasModifiers(member, PUBLIC) && !hasModifiers(member, STATIC);
+ }
+
+ static boolean hasModifiers(Element member, Modifier... modifiers) {
+ if (member == null || modifiers == null) {
+ return false;
+ }
+ Set<Modifier> actualModifiers = member.getModifiers();
+ for (Modifier modifier : modifiers) {
+ if (!actualModifiers.contains(modifier)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static List<? extends Element> getDeclaredMembers(TypeMirror type) {
+ TypeElement element = ofTypeElement(type);
+ return element == null ? emptyList() : element.getEnclosedElements();
+ }
+
+ static List<? extends Element> getAllDeclaredMembers(TypeMirror type) {
+ return getHierarchicalTypes(type)
+ .stream()
+ .map(MemberUtils::getDeclaredMembers)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ static boolean matchParameterTypes(List<? extends VariableElement> parameters, CharSequence... parameterTypes) {
+
+ int size = parameters.size();
+
+ if (size != parameterTypes.length) {
+ return false;
+ }
+
+ for (int i = 0; i < size; i++) {
+ VariableElement parameter = parameters.get(i);
+ if (!Objects.equals(parameter.asType().toString(), parameterTypes[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java
new file mode 100644
index 0000000..ab7c8c7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.ElementKind.METHOD;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filter;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.isPublicNonStatic;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matchParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+
+/**
+ * The utilities class for method in the package "javax.lang.model."
+ *
+ * @since 2.7.5
+ */
+public interface MethodUtils {
+
+ static List<ExecutableElement> getDeclaredMethods(TypeElement type, Predicate<ExecutableElement>... methodFilters) {
+ return type == null ? emptyList() : getDeclaredMethods(type.asType(), methodFilters);
+ }
+
+ static List<ExecutableElement> getDeclaredMethods(TypeMirror type, Predicate<ExecutableElement>... methodFilters) {
+ return filterAll(methodsIn(getDeclaredMembers(type)), methodFilters);
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeElement type, Predicate<ExecutableElement>... methodFilters) {
+ return type == null ? emptyList() : getAllDeclaredMethods(type.asType(), methodFilters);
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeElement type) {
+ return getAllDeclaredMethods(type, EMPTY_ARRAY);
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type, Predicate<ExecutableElement>... methodFilters) {
+ return getHierarchicalTypes(type)
+ .stream()
+ .map(t -> getDeclaredMethods(t, methodFilters))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type) {
+ return getAllDeclaredMethods(type, EMPTY_ARRAY);
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeElement type, Type... excludedTypes) {
+ return type == null ? emptyList() : getAllDeclaredMethods(type.asType(), excludedTypes);
+ }
+
+ static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type, Type... excludedTypes) {
+ return getHierarchicalTypes(type, excludedTypes)
+ .stream()
+ .map(t -> getDeclaredMethods(t))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ static List<ExecutableElement> getPublicNonStaticMethods(TypeElement type, Type... excludedTypes) {
+ return getPublicNonStaticMethods(ofDeclaredType(type), excludedTypes);
+ }
+
+ static List<ExecutableElement> getPublicNonStaticMethods(TypeMirror type, Type... excludedTypes) {
+ return filter(getAllDeclaredMethods(type, excludedTypes), MethodUtils::isPublicNonStaticMethod);
+ }
+
+ static boolean isMethod(ExecutableElement method) {
+ return method == null ? false : METHOD.equals(method.getKind());
+ }
+
+ static boolean isPublicNonStaticMethod(ExecutableElement method) {
+ return isMethod(method) && isPublicNonStatic(method);
+ }
+
+ static ExecutableElement findMethod(TypeElement type, String methodName, Type oneParameterType, Type... otherParameterTypes) {
+ return type == null ? null : findMethod(type.asType(), methodName, oneParameterType, otherParameterTypes);
+ }
+
+ static ExecutableElement findMethod(TypeMirror type, String methodName, Type oneParameterType, Type... otherParameterTypes) {
+ List<Type> parameterTypes = new LinkedList<>();
+ parameterTypes.add(oneParameterType);
+ parameterTypes.addAll(asList(otherParameterTypes));
+ return findMethod(type, methodName, parameterTypes.stream().map(Type::getTypeName).toArray(String[]::new));
+ }
+
+ static ExecutableElement findMethod(TypeElement type, String methodName, CharSequence... parameterTypes) {
+ return type == null ? null : findMethod(type.asType(), methodName, parameterTypes);
+ }
+
+ static ExecutableElement findMethod(TypeMirror type, String methodName, CharSequence... parameterTypes) {
+ return filterFirst(getAllDeclaredMethods(type),
+ method -> methodName.equals(method.getSimpleName().toString()),
+ method -> matchParameterTypes(method.getParameters(), parameterTypes)
+ );
+ }
+
+ static ExecutableElement getOverrideMethod(ProcessingEnvironment processingEnv, TypeElement type,
+ ExecutableElement declaringMethod) {
+ Elements elements = processingEnv.getElementUtils();
+ return filterFirst(getAllDeclaredMethods(type), method -> elements.overrides(method, declaringMethod, type));
+ }
+
+
+ static String getMethodName(ExecutableElement method) {
+ return method == null ? null : method.getSimpleName().toString();
+ }
+
+ static String getReturnType(ExecutableElement method) {
+ return method == null ? null : method.getReturnType().toString();
+ }
+
+ static String[] getMethodParameterTypes(ExecutableElement method) {
+ return method == null ?
+ new String[0] :
+ method.getParameters()
+ .stream()
+ .map(Element::asType)
+ .map(TypeMirror::toString)
+ .toArray(String[]::new);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java
new file mode 100644
index 0000000..889e59f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.TypeElement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.lang.String.valueOf;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+
+/**
+ * The utilities class for @Service annotation
+ *
+ * @since 2.7.5
+ */
+public interface ServiceAnnotationUtils {
+
+ /**
+ * The class name of @Service
+ */
+ String SERVICE_ANNOTATION_TYPE = "org.apache.dubbo.config.annotation.Service";
+
+ /**
+ * The class name of the legacy @Service
+ */
+ @Deprecated
+ String LEGACY_SERVICE_ANNOTATION_TYPE = "com.alibaba.dubbo.config.annotation.Service";
+
+ /**
+ * the attribute name of @Service.interfaceClass()
+ */
+ String INTERFACE_CLASS_ATTRIBUTE_NAME = "interfaceClass";
+
+ /**
+ * the attribute name of @Service.interfaceName()
+ */
+ String INTERFACE_NAME_ATTRIBUTE_NAME = "interfaceName";
+
+ /**
+ * the attribute name of @Service.group()
+ */
+ String GROUP_ATTRIBUTE_NAME = "group";
+
+ /**
+ * the attribute name of @Service.version()
+ */
+ String VERSION_ATTRIBUTE_NAME = "version";
+
+ Set<String> SUPPORTED_ANNOTATION_TYPES = unmodifiableSet(new HashSet(asList(SERVICE_ANNOTATION_TYPE, LEGACY_SERVICE_ANNOTATION_TYPE)));
+
+ static boolean isServiceAnnotationPresent(TypeElement annotatedType) {
+ return isAnnotationPresent(annotatedType, SERVICE_ANNOTATION_TYPE) ||
+ isAnnotationPresent(annotatedType, LEGACY_SERVICE_ANNOTATION_TYPE);
+ }
+
+ static AnnotationMirror getAnnotation(TypeElement annotatedClass) {
+ return getAnnotation(annotatedClass.getAnnotationMirrors());
+ }
+
+ static AnnotationMirror getAnnotation(Iterable<? extends AnnotationMirror> annotationMirrors) {
+ AnnotationMirror matchedAnnotationMirror = null;
+ for (AnnotationMirror annotationMirror : annotationMirrors) {
+ String annotationType = annotationMirror.getAnnotationType().toString();
+ if (SERVICE_ANNOTATION_TYPE.equals(annotationType)) {
+ matchedAnnotationMirror = annotationMirror;
+ break;
+ } else if (LEGACY_SERVICE_ANNOTATION_TYPE.equals(annotationType)) {
+ matchedAnnotationMirror = annotationMirror;
+ }
+ }
+
+ if (matchedAnnotationMirror == null) {
+ throw new IllegalArgumentException("The annotated element must be implemented the interface "
+ + SERVICE_ANNOTATION_TYPE + " or " + LEGACY_SERVICE_ANNOTATION_TYPE);
+ }
+
+ return matchedAnnotationMirror;
+ }
+
+ static String resolveServiceInterfaceName(TypeElement annotatedClass, AnnotationMirror serviceAnnotation) {
+ Object interfaceClass = getAttribute(serviceAnnotation, INTERFACE_CLASS_ATTRIBUTE_NAME);
+
+ if (interfaceClass == null) { // try to find the "interfaceName" attribute
+ interfaceClass = getAttribute(serviceAnnotation, INTERFACE_NAME_ATTRIBUTE_NAME);
+ }
+
+ if (interfaceClass == null) {
+ // last, get the interface class from first one
+ interfaceClass = ((TypeElement) annotatedClass).getInterfaces().get(0);
+ }
+
+ return valueOf(interfaceClass);
+ }
+
+ static String getGroup(AnnotationMirror serviceAnnotation) {
+ return getAttribute(serviceAnnotation, GROUP_ATTRIBUTE_NAME);
+ }
+
+ static String getVersion(AnnotationMirror serviceAnnotation) {
+ return getAttribute(serviceAnnotation, VERSION_ATTRIBUTE_NAME);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java
new file mode 100644
index 0000000..3283d50
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java
@@ -0,0 +1,382 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import static java.lang.String.valueOf;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySet;
+import static java.util.stream.Collectors.toSet;
+import static java.util.stream.Stream.of;
+import static java.util.stream.StreamSupport.stream;
+import static javax.lang.model.element.ElementKind.ANNOTATION_TYPE;
+import static javax.lang.model.element.ElementKind.CLASS;
+import static javax.lang.model.element.ElementKind.ENUM;
+import static javax.lang.model.element.ElementKind.INTERFACE;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+
+/**
+ * The utilities class for type in the package "javax.lang.model.*"
+ *
+ * @since 2.7.5
+ */
+public interface TypeUtils {
+
+ List<String> SIMPLE_TYPES = asList(
+ Void.class.getName(),
+ Boolean.class.getName(),
+ Character.class.getName(),
+ Byte.class.getName(),
+ Short.class.getName(),
+ Integer.class.getName(),
+ Long.class.getName(),
+ Float.class.getName(),
+ Double.class.getName(),
+ String.class.getName(),
+ BigDecimal.class.getName(),
+ BigInteger.class.getName(),
+ Date.class.getName()
+ );
+
+ static boolean isSimpleType(Element element) {
+ return element != null && isSimpleType(element.asType());
+ }
+
+ static boolean isSimpleType(TypeMirror type) {
+ return type != null && SIMPLE_TYPES.contains(type.toString());
+ }
+
+ static boolean isSameType(TypeMirror type, CharSequence typeName) {
+ if (type == null || typeName == null) {
+ return false;
+ }
+ return Objects.equals(valueOf(type), valueOf(typeName));
+ }
+
+ static boolean isSameType(TypeMirror typeMirror, Type type) {
+ return type != null && isSameType(typeMirror, type.getTypeName());
+ }
+
+ static boolean isArrayType(TypeMirror type) {
+ return type != null && TypeKind.ARRAY.equals(type.getKind());
+ }
+
+ static boolean isArrayType(Element element) {
+ return element != null && isArrayType(element.asType());
+ }
+
+ static boolean isEnumType(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ return declaredType != null && ENUM.equals(declaredType.asElement().getKind());
+ }
+
+ static boolean isEnumType(Element element) {
+ return element != null && isEnumType(element.asType());
+ }
+
+ static boolean isClassType(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ return declaredType != null && isClassType(declaredType.asElement());
+ }
+
+ static boolean isClassType(Element element) {
+ return element != null && CLASS.equals(element.getKind());
+ }
+
+ static boolean isPrimitiveType(TypeMirror type) {
+ return type != null && type.getKind().isPrimitive();
+ }
+
+ static boolean isPrimitiveType(Element element) {
+ return element != null && isPrimitiveType(element.asType());
+ }
+
+ static boolean isInterfaceType(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ return declaredType != null && isInterfaceType(declaredType.asElement());
+ }
+
+ static boolean isInterfaceType(Element element) {
+ return element != null && INTERFACE.equals(element.getKind());
+ }
+
+ static boolean isAnnotationType(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ return declaredType != null && isAnnotationType(declaredType.asElement());
+ }
+
+ static boolean isAnnotationType(Element element) {
+ return element != null && ANNOTATION_TYPE.equals(element.getKind());
+ }
+
+ static Set<TypeElement> getHierarchicalTypes(TypeElement type) {
+ return getHierarchicalTypes(type, true, true, true);
+ }
+
+ static Set<DeclaredType> getHierarchicalTypes(TypeMirror type) {
+ return getHierarchicalTypes(type, EMPTY_ARRAY);
+ }
+
+ static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, Predicate<DeclaredType>... typeFilters) {
+ return filterAll(ofDeclaredTypes(getHierarchicalTypes(ofTypeElement(type))), typeFilters);
+ }
+
+ static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, Type... excludedTypes) {
+ return getHierarchicalTypes(type, of(excludedTypes).map(Type::getTypeName).toArray(String[]::new));
+ }
+
+ static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, CharSequence... excludedTypeNames) {
+ Set<String> typeNames = of(excludedTypeNames).map(CharSequence::toString).collect(toSet());
+ return getHierarchicalTypes(type, t -> !typeNames.contains(t.toString()));
+ }
+
+ static Set<TypeElement> getHierarchicalTypes(TypeElement type,
+ boolean includeSelf,
+ boolean includeSuperTypes,
+ boolean includeSuperInterfaces,
+ Predicate<TypeElement>... typeFilters) {
+
+ if (type == null) {
+ return emptySet();
+ }
+
+ Set<TypeElement> hierarchicalTypes = new LinkedHashSet<>();
+
+ if (includeSelf) {
+ hierarchicalTypes.add(type);
+ }
+
+ if (includeSuperTypes) {
+ hierarchicalTypes.addAll(getAllSuperTypes(type));
+ }
+
+ if (includeSuperInterfaces) {
+ hierarchicalTypes.addAll(getAllInterfaces(type));
+ }
+
+ return filterAll(hierarchicalTypes, typeFilters);
+ }
+
+ static Set<DeclaredType> getHierarchicalTypes(TypeMirror type,
+ boolean includeSelf,
+ boolean includeSuperTypes,
+ boolean includeSuperInterfaces) {
+ return ofDeclaredTypes(getHierarchicalTypes(ofTypeElement(type),
+ includeSelf,
+ includeSuperTypes,
+ includeSuperInterfaces));
+ }
+
+ static List<TypeMirror> getInterfaces(TypeElement type, Predicate<TypeMirror>... interfaceFilters) {
+ return type == null ? emptyList() : filterAll((List<TypeMirror>) ofTypeElement(type).getInterfaces(), interfaceFilters);
+ }
+
+ static List<TypeMirror> getInterfaces(TypeMirror type, Predicate<TypeMirror>... interfaceFilters) {
+ return getInterfaces(ofTypeElement(type), interfaceFilters);
+ }
+
+ static Set<TypeElement> getAllInterfaces(TypeElement type, Predicate<TypeElement>... interfaceFilters) {
+ return type == null ? emptySet() : filterAll(ofTypeElements(getAllInterfaces(type.asType())), interfaceFilters);
+ }
+
+ static Set<? extends TypeMirror> getAllInterfaces(TypeMirror type, Predicate<TypeMirror>... interfaceFilters) {
+ if (type == null) {
+ return emptySet();
+ }
+ Set<TypeMirror> allInterfaces = new LinkedHashSet<>();
+ getInterfaces(type).forEach(i -> {
+ // Add current type's interfaces
+ allInterfaces.add(i);
+ // Add
+ allInterfaces.addAll(getAllInterfaces(i));
+ });
+ // Add all super types' interfaces
+ getAllSuperTypes(type).forEach(superType -> allInterfaces.addAll(getAllInterfaces(superType)));
+ return filterAll(allInterfaces, interfaceFilters);
+ }
+
+ static TypeElement getType(ProcessingEnvironment processingEnv, Type type) {
+ return type == null ? null : getType(processingEnv, type.getTypeName());
+ }
+
+ static TypeElement getType(ProcessingEnvironment processingEnv, TypeMirror type) {
+ return type == null ? null : getType(processingEnv, type.toString());
+ }
+
+ static TypeElement getType(ProcessingEnvironment processingEnv, CharSequence typeName) {
+ if (processingEnv == null || typeName == null) {
+ return null;
+ }
+ Elements elements = processingEnv.getElementUtils();
+ return elements.getTypeElement(typeName);
+ }
+
+ static TypeElement getSuperType(TypeElement type) {
+ return type == null ? null : ofTypeElement(type.getSuperclass());
+ }
+
+ static DeclaredType getSuperType(TypeMirror type) {
+ TypeElement superType = getSuperType(ofTypeElement(type));
+ return superType == null ? null : ofDeclaredType(superType.asType());
+ }
+
+ static Set<TypeElement> getAllSuperTypes(TypeElement type) {
+ return getAllSuperTypes(type, EMPTY_ARRAY);
+ }
+
+ static Set<TypeElement> getAllSuperTypes(TypeElement type, Predicate<TypeElement>... typeFilters) {
+ if (type == null) {
+ return emptySet();
+ }
+
+ Set<TypeElement> allSuperTypes = new LinkedHashSet<>();
+ TypeElement superType = getSuperType(type);
+ if (superType != null) {
+ // add super type
+ allSuperTypes.add(superType);
+ // add ancestors' types
+ allSuperTypes.addAll(getAllSuperTypes(superType));
+ }
+ return filterAll(allSuperTypes, typeFilters);
+ }
+
+ static Set<DeclaredType> getAllSuperTypes(TypeMirror type) {
+ return getAllSuperTypes(type, EMPTY_ARRAY);
+ }
+
+ static Set<DeclaredType> getAllSuperTypes(TypeMirror type, Predicate<DeclaredType>... typeFilters) {
+ return filterAll(ofDeclaredTypes(getAllSuperTypes(ofTypeElement(type))), typeFilters);
+ }
+
+ static boolean isDeclaredType(Element element) {
+ return element != null && isDeclaredType(element.asType());
+ }
+
+ static boolean isDeclaredType(TypeMirror type) {
+ return type instanceof DeclaredType;
+ }
+
+ static DeclaredType ofDeclaredType(Element element) {
+ return element == null ? null : ofDeclaredType(element.asType());
+ }
+
+ static DeclaredType ofDeclaredType(TypeMirror type) {
+ return isDeclaredType(type) ? DeclaredType.class.cast(type) : null;
+ }
+
+ static boolean isTypeElement(Element element) {
+ return element instanceof TypeElement;
+ }
+
+ static boolean isTypeElement(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ return declaredType != null && isTypeElement(declaredType.asElement());
+ }
+
+ static TypeElement ofTypeElement(Element element) {
+ return isTypeElement(element) ? TypeElement.class.cast(element) : null;
+ }
+
+ static TypeElement ofTypeElement(TypeMirror type) {
+ DeclaredType declaredType = ofDeclaredType(type);
+ if (declaredType != null) {
+ return ofTypeElement(declaredType.asElement());
+ }
+ return null;
+ }
+
+ static Set<DeclaredType> ofDeclaredTypes(Iterable<? extends Element> elements) {
+ return elements == null ?
+ emptySet() :
+ stream(elements.spliterator(), false)
+ .map(TypeUtils::ofTypeElement)
+ .filter(Objects::nonNull)
+ .map(Element::asType)
+ .map(TypeUtils::ofDeclaredType)
+ .filter(Objects::nonNull)
+ .collect(LinkedHashSet::new, Set::add, Set::addAll);
+ }
+
+ static Set<TypeElement> ofTypeElements(Iterable<? extends TypeMirror> types) {
+ return types == null ?
+ emptySet() :
+ stream(types.spliterator(), false)
+ .map(TypeUtils::ofTypeElement)
+ .filter(Objects::nonNull)
+ .collect(LinkedHashSet::new, Set::add, Set::addAll);
+ }
+
+ static List<DeclaredType> listDeclaredTypes(Iterable<? extends Element> elements) {
+ return new ArrayList<>(ofDeclaredTypes(elements));
+ }
+
+ static List<TypeElement> listTypeElements(Iterable<? extends TypeMirror> types) {
+ return new ArrayList<>(ofTypeElements(types));
+ }
+
+ static URL getResource(ProcessingEnvironment processingEnv, Element type) {
+ return getResource(processingEnv, ofDeclaredType(type));
+ }
+
+ static URL getResource(ProcessingEnvironment processingEnv, TypeMirror type) {
+ return type == null ? null : getResource(processingEnv, type.toString());
+ }
+
+ static URL getResource(ProcessingEnvironment processingEnv, CharSequence type) {
+ String relativeName = getResourceName(type);
+ URL resource = null;
+ try {
+ if (relativeName != null) {
+ FileObject fileObject = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", relativeName);
+ resource = fileObject.toUri().toURL();
+ // try to open it
+ resource.getContent();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return resource;
+ }
+
+ static String getResourceName(CharSequence type) {
+ return type == null ? null : type.toString().replace('.', '/').concat(".class");
+ }
+}
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..6c5909c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1,2 @@
+org.apache.dubbo.metadata.annotation.processing.ServiceDefinitionMetadataAnnotationProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataAnnotationProcessor
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
new file mode 100644
index 0000000..2ec903a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
@@ -0,0 +1,7 @@
+org.apache.dubbo.metadata.annotation.processing.builder.ArrayTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.CollectionTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.EnumTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.GeneralTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.MapTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.PrimitiveTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.SimpleTypeDefinitionBuilder
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
new file mode 100644
index 0000000..0428626
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
@@ -0,0 +1,10 @@
+# JAX-RS's implementations
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.QueryParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.FormParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.MatrixParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.HeaderParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.DefaultValueParameterProcessor
+
+# Spring Web MVC's implementations
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.RequestParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.RequestHeaderParameterProcessor
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor
new file mode 100644
index 0000000..43c307d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor
@@ -0,0 +1,3 @@
+# org.apache.dubbo.metadata.annotation.processing.rest.DefaultServiceRestMetadataProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.JAXRSServiceRestMetadataProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.SpringMvcServiceRestMetadataProcessor
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.java
new file mode 100644
index 0000000..0e5adf4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing;
+
+import org.apache.dubbo.metadata.annotation.processing.util.TypeUtils;
+import org.apache.dubbo.metadata.tools.Compiler;
+import org.apache.dubbo.metadata.tools.TestProcessor;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Abstract {@link Annotation} Processing Test case
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractAnnotationProcessingTest {
+
+ protected ProcessingEnvironment processingEnv;
+
+ protected Elements elements;
+
+ protected Types types;
+
+ @BeforeEach
+ public final void init() throws IOException {
+ Set<Class<?>> classesToBeCompiled = new LinkedHashSet<>();
+ classesToBeCompiled.add(getClass());
+ addCompiledClasses(classesToBeCompiled);
+ TestProcessor testProcessor = new TestProcessor();
+ Compiler compiler = new Compiler();
+ compiler.processors(testProcessor);
+ compiler.compile(classesToBeCompiled.toArray(new Class[0]));
+ processingEnv = testProcessor.getProcessingEnvironment();
+ elements = processingEnv.getElementUtils();
+ types = processingEnv.getTypeUtils();
+ beforeEach();
+ }
+
+ protected abstract void addCompiledClasses(Set<Class<?>> classesToBeCompiled);
+
+ protected abstract void beforeEach();
+
+ protected TypeElement getType(Class<?> type) {
+ return TypeUtils.getType(processingEnv, type);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..efab557
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link ArrayTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class ArrayTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private ArrayTypeDefinitionBuilder builder;
+
+ private TypeElement testType;
+
+ private VariableElement integersField;
+
+ private VariableElement stringsField;
+
+ private VariableElement primitiveTypeModelsField;
+
+ private VariableElement modelsField;
+
+ private VariableElement colorsField;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(ArrayTypeModel.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new ArrayTypeDefinitionBuilder();
+ testType = getType(ArrayTypeModel.class);
+ integersField = findField(testType, "integers");
+ stringsField = findField(testType, "strings");
+ primitiveTypeModelsField = findField(testType, "primitiveTypeModels");
+ modelsField = findField(testType, "models");
+ colorsField = findField(testType, "colors");
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, integersField.asType()));
+ assertTrue(builder.accept(processingEnv, stringsField.asType()));
+ assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+ assertTrue(builder.accept(processingEnv, modelsField.asType()));
+ assertTrue(builder.accept(processingEnv, colorsField.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+
+ buildAndAssertTypeDefinition(processingEnv, integersField, "int[]", "int", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, stringsField, "java.lang.String[]", "java.lang.String", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+ "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel[]",
+ "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, modelsField,
+ "org.apache.dubbo.metadata.annotation.processing.model.Model[]",
+ "org.apache.dubbo.metadata.annotation.processing.model.Model", builder, (def, subDef) -> {
+ TypeElement subType = elements.getTypeElement(subDef.getType());
+ assertEquals(ElementKind.CLASS, subType.getKind());
+ });
+
+ buildAndAssertTypeDefinition(processingEnv, colorsField,
+ "org.apache.dubbo.metadata.annotation.processing.model.Color[]",
+ "org.apache.dubbo.metadata.annotation.processing.model.Color", builder, (def, subDef) -> {
+ TypeElement subType = elements.getTypeElement(subDef.getType());
+ assertEquals(ElementKind.ENUM, subType.getKind());
+ });
+
+ }
+
+ static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
+ String expectedType, String compositeType, TypeDefinitionBuilder builder,
+ BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
+ TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+ TypeDefinition subTypeDefinition = typeDefinition.getItems().get(0);
+ assertEquals(expectedType, typeDefinition.getType());
+ assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+ assertEquals(compositeType, subTypeDefinition.getType());
+// assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+ Stream.of(assertions).forEach(assertion -> assertion.accept(typeDefinition, subTypeDefinition));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..1bfb32e
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.CollectionTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.ArrayTypeDefinitionBuilderTest.buildAndAssertTypeDefinition;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link CollectionTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class CollectionTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private CollectionTypeDefinitionBuilder builder;
+
+ private VariableElement stringsField;
+
+ private VariableElement colorsField;
+
+ private VariableElement primitiveTypeModelsField;
+
+ private VariableElement modelsField;
+
+ private VariableElement modelArraysField;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(CollectionTypeModel.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new CollectionTypeDefinitionBuilder();
+ TypeElement testType = getType(CollectionTypeModel.class);
+ stringsField = findField( testType, "strings");
+ colorsField = findField( testType, "colors");
+ primitiveTypeModelsField = findField( testType, "primitiveTypeModels");
+ modelsField = findField( testType, "models");
+ modelArraysField = findField( testType, "modelArrays");
+
+ assertEquals("strings", stringsField.getSimpleName().toString());
+ assertEquals("colors", colorsField.getSimpleName().toString());
+ assertEquals("primitiveTypeModels", primitiveTypeModelsField.getSimpleName().toString());
+ assertEquals("models", modelsField.getSimpleName().toString());
+ assertEquals("modelArrays", modelArraysField.getSimpleName().toString());
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, stringsField.asType()));
+ assertTrue(builder.accept(processingEnv, colorsField.asType()));
+ assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+ assertTrue(builder.accept(processingEnv, modelsField.asType()));
+ assertTrue(builder.accept(processingEnv, modelArraysField.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+
+ buildAndAssertTypeDefinition(processingEnv, stringsField, "java.util.Collection<java.lang.String>", "java.lang.String", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, colorsField, "java.util.List<org.apache.dubbo.metadata.annotation.processing.model.Color>",
+ "org.apache.dubbo.metadata.annotation.processing.model.Color", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+ "java.util.Queue<org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel>",
+ "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, modelsField,
+ "java.util.Deque<org.apache.dubbo.metadata.annotation.processing.model.Model>",
+ "org.apache.dubbo.metadata.annotation.processing.model.Model", builder);
+
+ buildAndAssertTypeDefinition(processingEnv, modelArraysField,
+ "java.util.Set<org.apache.dubbo.metadata.annotation.processing.model.Model[]>",
+ "org.apache.dubbo.metadata.annotation.processing.model.Model[]", builder);
+
+
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..52f33aa
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder.build;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link EnumTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class EnumTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private EnumTypeDefinitionBuilder builder;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(Color.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new EnumTypeDefinitionBuilder();
+ }
+
+ @Test
+ public void testAccept() {
+ TypeElement typeElement = getType(Color.class);
+ assertTrue(builder.accept(processingEnv, typeElement.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+ TypeElement typeElement = getType(Color.class);
+ TypeDefinition typeDefinition = build(processingEnv, typeElement);
+ assertEquals(Color.class.getName(), typeDefinition.getType());
+ assertEquals(asList("RED", "YELLOW", "BLUE"), typeDefinition.getEnums());
+// assertEquals(typeDefinition.getTypeBuilderName(), builder.getClass().getName());
+ }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..8be38dc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.CollectionTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.SimpleTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link GeneralTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class GeneralTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private GeneralTypeDefinitionBuilder builder;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(Model.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new GeneralTypeDefinitionBuilder();
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, getType(Model.class).asType()));
+ assertTrue(builder.accept(processingEnv, getType(PrimitiveTypeModel.class).asType()));
+ assertTrue(builder.accept(processingEnv, getType(SimpleTypeModel.class).asType()));
+ assertTrue(builder.accept(processingEnv, getType(ArrayTypeModel.class).asType()));
+ assertTrue(builder.accept(processingEnv, getType(CollectionTypeModel.class).asType()));
+ assertFalse(builder.accept(processingEnv, getType(Color.class).asType()));
+ }
+
+ @Test
+ public void testBuild() {
+
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..3229c31
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.MapTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link MapTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class MapTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private MapTypeDefinitionBuilder builder;
+
+ private VariableElement stringsField;
+
+ private VariableElement colorsField;
+
+ private VariableElement primitiveTypeModelsField;
+
+ private VariableElement modelsField;
+
+ private VariableElement modelArraysField;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(MapTypeModel.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new MapTypeDefinitionBuilder();
+ TypeElement testType = getType(MapTypeModel.class);
+ stringsField = findField( testType, "strings");
+ colorsField = findField( testType, "colors");
+ primitiveTypeModelsField = findField( testType, "primitiveTypeModels");
+ modelsField = findField( testType, "models");
+ modelArraysField = findField( testType, "modelArrays");
+
+ assertEquals("strings", stringsField.getSimpleName().toString());
+ assertEquals("colors", colorsField.getSimpleName().toString());
+ assertEquals("primitiveTypeModels", primitiveTypeModelsField.getSimpleName().toString());
+ assertEquals("models", modelsField.getSimpleName().toString());
+ assertEquals("modelArrays", modelArraysField.getSimpleName().toString());
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, stringsField.asType()));
+ assertTrue(builder.accept(processingEnv, colorsField.asType()));
+ assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+ assertTrue(builder.accept(processingEnv, modelsField.asType()));
+ assertTrue(builder.accept(processingEnv, modelArraysField.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+
+ buildAndAssertTypeDefinition(processingEnv, stringsField,
+ "java.util.Map<java.lang.String,java.lang.String>",
+ "java.lang.String",
+ "java.lang.String",
+ builder);
+
+ buildAndAssertTypeDefinition(processingEnv, colorsField,
+ "java.util.SortedMap<java.lang.String,org.apache.dubbo.metadata.annotation.processing.model.Color>",
+ "java.lang.String",
+ "org.apache.dubbo.metadata.annotation.processing.model.Color",
+ builder);
+
+ buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+ "java.util.NavigableMap<org.apache.dubbo.metadata.annotation.processing.model.Color,org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel>",
+ "org.apache.dubbo.metadata.annotation.processing.model.Color",
+ "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel",
+ builder);
+
+ buildAndAssertTypeDefinition(processingEnv, modelsField,
+ "java.util.HashMap<java.lang.String,org.apache.dubbo.metadata.annotation.processing.model.Model>",
+ "java.lang.String",
+ "org.apache.dubbo.metadata.annotation.processing.model.Model",
+ builder);
+
+ buildAndAssertTypeDefinition(processingEnv, modelArraysField,
+ "java.util.TreeMap<org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel,org.apache.dubbo.metadata.annotation.processing.model.Model[]>",
+ "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel",
+ "org.apache.dubbo.metadata.annotation.processing.model.Model[]",
+ builder);
+ }
+
+ static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
+ String expectedType, String keyType, String valueType,
+ TypeDefinitionBuilder builder,
+ BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
+ TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+ TypeDefinition keyTypeDefinition = typeDefinition.getItems().get(0);
+ TypeDefinition valueTypeDefinition = typeDefinition.getItems().get(1);
+ assertEquals(expectedType, typeDefinition.getType());
+ assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+ assertEquals(keyType, keyTypeDefinition.getType());
+ assertEquals(valueType, valueTypeDefinition.getType());
+// assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+ Stream.of(assertions).forEach(assertion -> assertion.accept(typeDefinition, keyTypeDefinition));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..0953885
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link PrimitiveTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class PrimitiveTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private PrimitiveTypeDefinitionBuilder builder;
+
+ private VariableElement zField;
+
+ private VariableElement bField;
+
+ private VariableElement cField;
+
+ private VariableElement sField;
+
+ private VariableElement iField;
+
+ private VariableElement lField;
+
+ private VariableElement fField;
+
+ private VariableElement dField;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(PrimitiveTypeModel.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+
+ builder = new PrimitiveTypeDefinitionBuilder();
+
+ TypeElement testType = getType(PrimitiveTypeModel.class);
+
+ zField = findField( testType, "z");
+ bField = findField( testType, "b");
+ cField = findField( testType, "c");
+ sField = findField( testType, "s");
+ iField = findField( testType, "i");
+ lField = findField( testType, "l");
+ fField = findField( testType, "f");
+ dField = findField( testType, "d");
+
+ assertEquals("boolean", zField.asType().toString());
+ assertEquals("byte", bField.asType().toString());
+ assertEquals("char", cField.asType().toString());
+ assertEquals("short", sField.asType().toString());
+ assertEquals("int", iField.asType().toString());
+ assertEquals("long", lField.asType().toString());
+ assertEquals("float", fField.asType().toString());
+ assertEquals("double", dField.asType().toString());
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, zField.asType()));
+ assertTrue(builder.accept(processingEnv, bField.asType()));
+ assertTrue(builder.accept(processingEnv, cField.asType()));
+ assertTrue(builder.accept(processingEnv, sField.asType()));
+ assertTrue(builder.accept(processingEnv, iField.asType()));
+ assertTrue(builder.accept(processingEnv, lField.asType()));
+ assertTrue(builder.accept(processingEnv, fField.asType()));
+ assertTrue(builder.accept(processingEnv, dField.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+ buildAndAssertTypeDefinition(processingEnv, zField, builder);
+ buildAndAssertTypeDefinition(processingEnv, bField, builder);
+ buildAndAssertTypeDefinition(processingEnv, cField, builder);
+ buildAndAssertTypeDefinition(processingEnv, sField, builder);
+ buildAndAssertTypeDefinition(processingEnv, iField, builder);
+ buildAndAssertTypeDefinition(processingEnv, lField, builder);
+ buildAndAssertTypeDefinition(processingEnv, zField, builder);
+ buildAndAssertTypeDefinition(processingEnv, fField, builder);
+ buildAndAssertTypeDefinition(processingEnv, dField, builder);
+ }
+
+ static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field, TypeDefinitionBuilder builder) {
+ TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+ assertBasicTypeDefinition(typeDefinition, field.asType().toString(), builder);
+ assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+ }
+
+ static void assertBasicTypeDefinition(TypeDefinition typeDefinition, String type, TypeDefinitionBuilder builder) {
+ assertEquals(type, typeDefinition.getType());
+// assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+ assertTrue(typeDefinition.getProperties().isEmpty());
+ assertTrue(typeDefinition.getItems().isEmpty());
+ assertTrue(typeDefinition.getEnums().isEmpty());
+ assertNull(typeDefinition.getId());
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.java
new file mode 100644
index 0000000..c891f87
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link ServiceDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class ServiceDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(TestServiceImpl.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ }
+
+ @Test
+ public void testBuild() {
+ ServiceDefinition serviceDefinition = build(processingEnv, getType(TestServiceImpl.class));
+ assertEquals(TestServiceImpl.class.getTypeName(), serviceDefinition.getCanonicalName());
+ assertEquals("org/apache/dubbo/metadata/tools/TestServiceImpl.class", serviceDefinition.getCodeSource());
+ // types
+ int i = 0;
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("java.lang.AutoCloseable", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("java.io.Serializable", serviceDefinition.getTypes().get(i++).getType());
+ assertEquals("java.util.EventListener", serviceDefinition.getTypes().get(i++).getType());
+ // methods
+ assertEquals(14, serviceDefinition.getMethods().size());
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..365ac56
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.SimpleTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.PrimitiveTypeDefinitionBuilderTest.buildAndAssertTypeDefinition;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link SimpleTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+ private SimpleTypeDefinitionBuilder builder;
+
+ private VariableElement vField;
+
+ private VariableElement zField;
+
+ private VariableElement cField;
+
+ private VariableElement bField;
+
+ private VariableElement sField;
+
+ private VariableElement iField;
+
+ private VariableElement lField;
+
+ private VariableElement fField;
+
+ private VariableElement dField;
+
+ private VariableElement strField;
+
+ private VariableElement bdField;
+
+ private VariableElement biField;
+
+ private VariableElement dtField;
+
+ private VariableElement invalidField;
+
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(SimpleTypeModel.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ builder = new SimpleTypeDefinitionBuilder();
+ TypeElement testType = getType(SimpleTypeModel.class);
+ vField = findField(testType, "v");
+ zField = findField(testType, "z");
+ cField = findField(testType, "c");
+ bField = findField(testType, "b");
+ sField = findField(testType, "s");
+ iField = findField(testType, "i");
+ lField = findField(testType, "l");
+ fField = findField(testType, "f");
+ dField = findField(testType, "d");
+ strField = findField(testType, "str");
+ bdField = findField(testType, "bd");
+ biField = findField(testType, "bi");
+ dtField = findField(testType, "dt");
+ invalidField = findField(testType, "invalid");
+
+ assertEquals("java.lang.Void", vField.asType().toString());
+ assertEquals("java.lang.Boolean", zField.asType().toString());
+ assertEquals("java.lang.Character", cField.asType().toString());
+ assertEquals("java.lang.Byte", bField.asType().toString());
+ assertEquals("java.lang.Short", sField.asType().toString());
+ assertEquals("java.lang.Integer", iField.asType().toString());
+ assertEquals("java.lang.Long", lField.asType().toString());
+ assertEquals("java.lang.Float", fField.asType().toString());
+ assertEquals("java.lang.Double", dField.asType().toString());
+ assertEquals("java.lang.String", strField.asType().toString());
+ assertEquals("java.math.BigDecimal", bdField.asType().toString());
+ assertEquals("java.math.BigInteger", biField.asType().toString());
+ assertEquals("java.util.Date", dtField.asType().toString());
+ assertEquals("int", invalidField.asType().toString());
+ }
+
+ @Test
+ public void testAccept() {
+ assertTrue(builder.accept(processingEnv, vField.asType()));
+ assertTrue(builder.accept(processingEnv, zField.asType()));
+ assertTrue(builder.accept(processingEnv, cField.asType()));
+ assertTrue(builder.accept(processingEnv, bField.asType()));
+ assertTrue(builder.accept(processingEnv, sField.asType()));
+ assertTrue(builder.accept(processingEnv, iField.asType()));
+ assertTrue(builder.accept(processingEnv, lField.asType()));
+ assertTrue(builder.accept(processingEnv, fField.asType()));
+ assertTrue(builder.accept(processingEnv, dField.asType()));
+ assertTrue(builder.accept(processingEnv, strField.asType()));
+ assertTrue(builder.accept(processingEnv, bdField.asType()));
+ assertTrue(builder.accept(processingEnv, biField.asType()));
+ assertTrue(builder.accept(processingEnv, dtField.asType()));
+ // false condition
+ assertFalse(builder.accept(processingEnv, invalidField.asType()));
+ }
+
+ @Test
+ public void testBuild() {
+ buildAndAssertTypeDefinition(processingEnv, vField, builder);
+ buildAndAssertTypeDefinition(processingEnv, zField, builder);
+ buildAndAssertTypeDefinition(processingEnv, cField, builder);
+ buildAndAssertTypeDefinition(processingEnv, sField, builder);
+ buildAndAssertTypeDefinition(processingEnv, iField, builder);
+ buildAndAssertTypeDefinition(processingEnv, lField, builder);
+ buildAndAssertTypeDefinition(processingEnv, fField, builder);
+ buildAndAssertTypeDefinition(processingEnv, dField, builder);
+ buildAndAssertTypeDefinition(processingEnv, strField, builder);
+ buildAndAssertTypeDefinition(processingEnv, bdField, builder);
+ buildAndAssertTypeDefinition(processingEnv, biField, builder);
+ buildAndAssertTypeDefinition(processingEnv, dtField, builder);
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
index b3b27e6..db6874a 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
@@ -14,27 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
/**
- * {@link DubboServiceLoader} Test
+ * Array Type Model
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class ArrayTypeModel {
+
+ private int[] integers; // Primitive type array
+
+ private String[] strings; // Simple type array
+
+ private PrimitiveTypeModel[] primitiveTypeModels; // Complex type array
+
+ private Model[] models; // Hierarchical Complex type array
+
+ private Color[] colors; // Enum type array
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
index b3b27e6..b2ce91d 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
@@ -14,27 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
-
-import org.junit.jupiter.api.Test;
+package org.apache.dubbo.metadata.annotation.processing.model;
+import java.util.Collection;
+import java.util.Deque;
import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.Queue;
+import java.util.Set;
/**
- * {@link DubboServiceLoader} Test
+ * {@link Collection} Type Model
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
+public class CollectionTypeModel {
+
+ private Collection<String> strings; // The composite element is simple type
+
+ private List<Color> colors; // The composite element is Enum type
+
+ private Queue<PrimitiveTypeModel> primitiveTypeModels; // The composite element is POJO type
+
+ private Deque<Model> models; // The composite element is hierarchical POJO type
+
+ private Set<Model[]> modelArrays; // The composite element is hierarchical POJO type
+
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
index b3b27e6..6c34404 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
@@ -14,27 +14,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
/**
- * {@link DubboServiceLoader} Test
+ * Color enumeration
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public enum Color {
+
+ RED(1),
+ YELLOW(2),
+ BLUE(3);
+
+ private final int value;
+
+ Color(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "Color{" +
+ "value=" + value +
+ "} " + super.toString();
+ }
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public int getValue() {
+ return value;
}
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
similarity index 53%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
index b3b27e6..f1613ae 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
@@ -14,27 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.model;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.SortedMap;
+import java.util.TreeMap;
/**
- * {@link DubboServiceLoader} Test
+ * {@link Map} Type model
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class MapTypeModel {
+
+ private Map<String, String> strings; // The composite element is simple type
+
+ private SortedMap<String, Color> colors; // The composite element is Enum type
+
+ private NavigableMap<Color, PrimitiveTypeModel> primitiveTypeModels; // The composite element is POJO type
+
+ private HashMap<String, Model> models; // The composite element is hierarchical POJO type
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
+ private TreeMap<PrimitiveTypeModel, Model[]> modelArrays; // The composite element is hierarchical POJO type
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java
new file mode 100644
index 0000000..e3c72a5
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.model;
+
+import org.apache.dubbo.metadata.tools.Parent;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Model Object
+ */
+public class Model extends Parent {
+
+ private float f;
+
+ private double d;
+
+ private TimeUnit tu;
+
+ private String str;
+
+ private BigInteger bi;
+
+ private BigDecimal bd;
+
+ public float getF() {
+ return f;
+ }
+
+ public void setF(float f) {
+ this.f = f;
+ }
+
+ public double getD() {
+ return d;
+ }
+
+ public void setD(double d) {
+ this.d = d;
+ }
+
+ public TimeUnit getTu() {
+ return tu;
+ }
+
+ public void setTu(TimeUnit tu) {
+ this.tu = tu;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public BigInteger getBi() {
+ return bi;
+ }
+
+ public void setBi(BigInteger bi) {
+ this.bi = bi;
+ }
+
+ public BigDecimal getBd() {
+ return bd;
+ }
+
+ public void setBd(BigDecimal bd) {
+ this.bd = bd;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
similarity index 54%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
index b3b27e6..7adc685 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
@@ -14,27 +14,60 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
/**
- * {@link DubboServiceLoader} Test
+ * Primitive Type model
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+public class PrimitiveTypeModel {
+
+ private boolean z;
+
+ private byte b;
+
+ private char c;
+
+ private short s;
+
+ private int i;
+
+ private long l;
+
+ private float f;
+
+ private double d;
+
+ public boolean isZ() {
+ return z;
+ }
+
+ public byte getB() {
+ return b;
+ }
+
+ public char getC() {
+ return c;
+ }
+
+ public short getS() {
+ return s;
+ }
+
+ public int getI() {
+ return i;
+ }
+
+ public long getL() {
+ return l;
+ }
+
+ public float getF() {
+ return f;
+ }
+
+ public double getD() {
+ return d;
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java
new file mode 100644
index 0000000..b6f40ec
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License; Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing; software
+ * distributed under the License is distributed on an "AS IS" BASIS;
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND; either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.model;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * Simple Type model
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeModel {
+
+ private Void v;
+
+ private Boolean z;
+
+ private Character c;
+
+ private Byte b;
+
+ private Short s;
+
+ private Integer i;
+
+ private Long l;
+
+ private Float f;
+
+ private Double d;
+
+ private String str;
+
+ private BigDecimal bd;
+
+ private BigInteger bi;
+
+ private Date dt;
+
+ private int invalid;
+
+ public Void getV() {
+ return v;
+ }
+
+ public void setV(Void v) {
+ this.v = v;
+ }
+
+ public Boolean getZ() {
+ return z;
+ }
+
+ public void setZ(Boolean z) {
+ this.z = z;
+ }
+
+ public Character getC() {
+ return c;
+ }
+
+ public void setC(Character c) {
+ this.c = c;
+ }
+
+ public Byte getB() {
+ return b;
+ }
+
+ public void setB(Byte b) {
+ this.b = b;
+ }
+
+ public Short getS() {
+ return s;
+ }
+
+ public void setS(Short s) {
+ this.s = s;
+ }
+
+ public Integer getI() {
+ return i;
+ }
+
+ public void setI(Integer i) {
+ this.i = i;
+ }
+
+ public Long getL() {
+ return l;
+ }
+
+ public void setL(Long l) {
+ this.l = l;
+ }
+
+ public Float getF() {
+ return f;
+ }
+
+ public void setF(Float f) {
+ this.f = f;
+ }
+
+ public Double getD() {
+ return d;
+ }
+
+ public void setD(Double d) {
+ this.d = d;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public BigDecimal getBd() {
+ return bd;
+ }
+
+ public void setBd(BigDecimal bd) {
+ this.bd = bd;
+ }
+
+ public BigInteger getBi() {
+ return bi;
+ }
+
+ public void setBi(BigInteger bi) {
+ this.bi = bi;
+ }
+
+ public Date getDt() {
+ return dt;
+ }
+
+ public void setDt(Date dt) {
+ this.dt = dt;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java
new file mode 100644
index 0000000..a68cc23
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.tools.SpringRestService;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.ws.rs.Path;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAllAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getAllDeclaredMethods;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The {@link AnnotationUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class AnnotationUtilsTest extends AbstractAnnotationProcessingTest {
+
+ private TypeElement testType;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ }
+
+ @Override
+ protected void beforeEach() {
+ testType = getType(TestServiceImpl.class);
+ }
+
+ @Test
+ public void testGetAnnotation() {
+ AnnotationMirror serviceAnnotation = getAnnotation(testType, Service.class);
+ assertEquals("3.0.0", getAttribute(serviceAnnotation, "version"));
+ assertEquals("test", getAttribute(serviceAnnotation, "group"));
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(serviceAnnotation, "interfaceName"));
+
+ assertNull(getAnnotation(testType, (Class) null));
+ assertNull(getAnnotation(testType, (String) null));
+
+ assertNull(getAnnotation(testType.asType(), (Class) null));
+ assertNull(getAnnotation(testType.asType(), (String) null));
+
+ assertNull(getAnnotation((Element) null, (Class) null));
+ assertNull(getAnnotation((Element) null, (String) null));
+
+ assertNull(getAnnotation((TypeElement) null, (Class) null));
+ assertNull(getAnnotation((TypeElement) null, (String) null));
+ }
+
+ @Test
+ public void testGetAnnotations() {
+ List<AnnotationMirror> annotations = getAnnotations(testType);
+ Iterator<AnnotationMirror> iterator = annotations.iterator();
+
+ assertEquals(2, annotations.size());
+ assertEquals("com.alibaba.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+ assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+ annotations = getAnnotations(testType, Service.class);
+ iterator = annotations.iterator();
+ assertEquals(1, annotations.size());
+ assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+ annotations = getAnnotations(testType.asType(), Service.class);
+ iterator = annotations.iterator();
+ assertEquals(1, annotations.size());
+ assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+ annotations = getAnnotations(testType.asType(), Service.class.getTypeName());
+ iterator = annotations.iterator();
+ assertEquals(1, annotations.size());
+ assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+ annotations = getAnnotations(testType, Override.class);
+ assertEquals(0, annotations.size());
+
+ annotations = getAnnotations(testType, com.alibaba.dubbo.config.annotation.Service.class);
+ assertEquals(1, annotations.size());
+
+ assertTrue(getAnnotations(null, (Class) null).isEmpty());
+ assertTrue(getAnnotations(null, (String) null).isEmpty());
+ assertTrue(getAnnotations(testType, (Class) null).isEmpty());
+ assertTrue(getAnnotations(testType, (String) null).isEmpty());
+
+ assertTrue(getAnnotations(null, Service.class).isEmpty());
+ assertTrue(getAnnotations(null, Service.class.getTypeName()).isEmpty());
+ }
+
+ @Test
+ public void testGetAllAnnotations() {
+
+ List<AnnotationMirror> annotations = getAllAnnotations(testType);
+ assertEquals(5, annotations.size());
+
+ annotations = getAllAnnotations(testType.asType(), annotation -> true);
+ assertEquals(5, annotations.size());
+
+ annotations = getAllAnnotations(processingEnv, TestServiceImpl.class);
+ assertEquals(5, annotations.size());
+
+ annotations = getAllAnnotations(testType.asType(), Service.class);
+ assertEquals(2, annotations.size());
+
+ annotations = getAllAnnotations(testType, Override.class);
+ assertEquals(0, annotations.size());
+
+ annotations = getAllAnnotations(testType.asType(), com.alibaba.dubbo.config.annotation.Service.class);
+ assertEquals(2, annotations.size());
+
+ assertTrue(getAllAnnotations((Element) null, (Class) null).isEmpty());
+ assertTrue(getAllAnnotations((TypeMirror) null, (String) null).isEmpty());
+ assertTrue(getAllAnnotations((ProcessingEnvironment) null, (Class) null).isEmpty());
+ assertTrue(getAllAnnotations((ProcessingEnvironment) null, (String) null).isEmpty());
+
+ assertTrue(getAllAnnotations((Element) null).isEmpty());
+ assertTrue(getAllAnnotations((TypeMirror) null).isEmpty());
+ assertTrue(getAllAnnotations(processingEnv, (Class) null).isEmpty());
+ assertTrue(getAllAnnotations(processingEnv, (String) null).isEmpty());
+
+
+ assertTrue(getAllAnnotations(testType, (Class) null).isEmpty());
+ assertTrue(getAllAnnotations(testType.asType(), (Class) null).isEmpty());
+
+ assertTrue(getAllAnnotations(testType, (String) null).isEmpty());
+ assertTrue(getAllAnnotations(testType.asType(), (String) null).isEmpty());
+
+ assertTrue(getAllAnnotations((Element) null, Service.class).isEmpty());
+ assertTrue(getAllAnnotations((TypeMirror) null, Service.class.getTypeName()).isEmpty());
+ }
+
+
+ @Test
+ public void testFindAnnotation() {
+
+ assertEquals("org.apache.dubbo.config.annotation.Service", findAnnotation(testType, Service.class).getAnnotationType().toString());
+ assertEquals("com.alibaba.dubbo.config.annotation.Service", findAnnotation(testType, com.alibaba.dubbo.config.annotation.Service.class).getAnnotationType().toString());
+ assertEquals("javax.ws.rs.Path", findAnnotation(testType, Path.class).getAnnotationType().toString());
+ assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class).getAnnotationType().toString());
+ assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class.getTypeName()).getAnnotationType().toString());
+ assertNull(findAnnotation(testType, Override.class));
+
+ assertNull(findAnnotation((Element) null, (Class) null));
+ assertNull(findAnnotation((Element) null, (String) null));
+ assertNull(findAnnotation((TypeMirror) null, (Class) null));
+ assertNull(findAnnotation((TypeMirror) null, (String) null));
+
+ assertNull(findAnnotation(testType, (Class) null));
+ assertNull(findAnnotation(testType, (String) null));
+ assertNull(findAnnotation(testType.asType(), (Class) null));
+ assertNull(findAnnotation(testType.asType(), (String) null));
+ }
+
+ @Test
+ public void testFindMetaAnnotation() {
+ getAllDeclaredMethods(getType(TestService.class)).forEach(method -> {
+ assertEquals("javax.ws.rs.HttpMethod", findMetaAnnotation(method, "javax.ws.rs.HttpMethod").getAnnotationType().toString());
+ });
+ }
+
+ @Test
+ public void testGetAttribute() {
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(findAnnotation(testType, Service.class), "interfaceName"));
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(findAnnotation(testType, Service.class).getElementValues(), "interfaceName"));
+ assertEquals("/echo", getAttribute(findAnnotation(testType, Path.class), "value"));
+
+ assertNull(getAttribute(findAnnotation(testType, Path.class), null));
+ assertNull(getAttribute(findAnnotation(testType, (Class) null), null));
+
+ ExecutableElement method = findMethod(getType(SpringRestService.class), "param", String.class);
+
+ AnnotationMirror annotation = findAnnotation(method, GetMapping.class);
+
+ assertArrayEquals(new String[]{"/param"}, (String[]) getAttribute(annotation, "value"));
+ assertNull(getAttribute(annotation, "path"));
+ }
+
+ @Test
+ public void testGetValue() {
+ AnnotationMirror pathAnnotation = getAnnotation(getType(TestService.class), Path.class);
+ assertEquals("/echo", getValue(pathAnnotation));
+ }
+
+ @Test
+ public void testIsAnnotationPresent() {
+ assertTrue(isAnnotationPresent(testType, "org.apache.dubbo.config.annotation.Service"));
+ assertTrue(isAnnotationPresent(testType, "com.alibaba.dubbo.config.annotation.Service"));
+ assertTrue(isAnnotationPresent(testType, "javax.ws.rs.Path"));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java
new file mode 100644
index 0000000..5776791
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getAllDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getAllNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isEnumMemberField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isNonStaticField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link FieldUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class FieldUtilsTest extends AbstractAnnotationProcessingTest {
+
+ private TypeElement testType;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ }
+
+ @Override
+ protected void beforeEach() {
+ testType = getType(TestServiceImpl.class);
+ }
+
+ @Test
+ public void testGetDeclaredFields() {
+ TypeElement type = getType(Model.class);
+ List<VariableElement> fields = getDeclaredFields(type);
+ assertModelFields(fields);
+
+ fields = getDeclaredFields(type.asType());
+ assertModelFields(fields);
+
+ assertTrue(getDeclaredFields((Element) null).isEmpty());
+ assertTrue(getDeclaredFields((TypeMirror) null).isEmpty());
+
+ fields = getDeclaredFields(type, f -> "f".equals(f.getSimpleName().toString()));
+ assertEquals(1, fields.size());
+ assertEquals("f", fields.get(0).getSimpleName().toString());
+ }
+
+ @Test
+ public void testGetAllDeclaredFields() {
+ TypeElement type = getType(Model.class);
+
+ List<VariableElement> fields = getAllDeclaredFields(type);
+
+ assertModelAllFields(fields);
+
+ assertTrue(getAllDeclaredFields((Element) null).isEmpty());
+ assertTrue(getAllDeclaredFields((TypeMirror) null).isEmpty());
+
+ fields = getAllDeclaredFields(type, f -> "f".equals(f.getSimpleName().toString()));
+ assertEquals(1, fields.size());
+ assertEquals("f", fields.get(0).getSimpleName().toString());
+ }
+
+ @Test
+ public void testGetDeclaredField() {
+ TypeElement type = getType(Model.class);
+ testGetDeclaredField(type, "f", float.class);
+ testGetDeclaredField(type, "d", double.class);
+ testGetDeclaredField(type, "tu", TimeUnit.class);
+ testGetDeclaredField(type, "str", String.class);
+ testGetDeclaredField(type, "bi", BigInteger.class);
+ testGetDeclaredField(type, "bd", BigDecimal.class);
+
+ assertNull(getDeclaredField(type, "b"));
+ assertNull(getDeclaredField(type, "s"));
+ assertNull(getDeclaredField(type, "i"));
+ assertNull(getDeclaredField(type, "l"));
+ assertNull(getDeclaredField(type, "z"));
+
+ assertNull(getDeclaredField((Element) null, "z"));
+ assertNull(getDeclaredField((TypeMirror) null, "z"));
+ }
+
+ @Test
+ public void testFindField() {
+ TypeElement type = getType(Model.class);
+ testFindField(type, "f", float.class);
+ testFindField(type, "d", double.class);
+ testFindField(type, "tu", TimeUnit.class);
+ testFindField(type, "str", String.class);
+ testFindField(type, "bi", BigInteger.class);
+ testFindField(type, "bd", BigDecimal.class);
+ testFindField(type, "b", byte.class);
+ testFindField(type, "s", short.class);
+ testFindField(type, "i", int.class);
+ testFindField(type, "l", long.class);
+ testFindField(type, "z", boolean.class);
+
+ assertNull(findField((Element) null, "f"));
+ assertNull(findField((Element) null, null));
+
+ assertNull(findField((TypeMirror) null, "f"));
+ assertNull(findField((TypeMirror) null, null));
+
+ assertNull(findField(type, null));
+ assertNull(findField(type.asType(), null));
+ }
+
+ @Test
+ public void testIsEnumField() {
+ TypeElement type = getType(Color.class);
+ VariableElement field = findField(type, "RED");
+ assertTrue(isEnumMemberField(field));
+
+ field = findField(type, "YELLOW");
+ assertTrue(isEnumMemberField(field));
+
+ field = findField(type, "BLUE");
+ assertTrue(isEnumMemberField(field));
+
+ type = getType(Model.class);
+ field = findField(type, "f");
+ assertFalse(isEnumMemberField(field));
+
+ assertFalse(isEnumMemberField(null));
+ }
+
+ @Test
+ public void testIsNonStaticField() {
+ TypeElement type = getType(Model.class);
+ assertTrue(isNonStaticField(findField(type, "f")));
+
+ type = getType(Color.class);
+ assertFalse(isNonStaticField(findField(type, "BLUE")));
+ }
+
+ @Test
+ public void testIsField() {
+ TypeElement type = getType(Model.class);
+ assertTrue(isField(findField(type, "f")));
+ assertTrue(isField(findField(type, "f"), PRIVATE));
+
+ type = getType(Color.class);
+ assertTrue(isField(findField(type, "BLUE"), PUBLIC, STATIC, FINAL));
+
+
+ assertFalse(isField(null));
+ assertFalse(isField(null, PUBLIC, STATIC, FINAL));
+ }
+
+ @Test
+ public void testGetNonStaticFields() {
+ TypeElement type = getType(Model.class);
+
+ List<VariableElement> fields = getNonStaticFields(type);
+ assertModelFields(fields);
+
+ fields = getNonStaticFields(type.asType());
+ assertModelFields(fields);
+
+ assertTrue(getAllNonStaticFields((Element) null).isEmpty());
+ assertTrue(getAllNonStaticFields((TypeMirror) null).isEmpty());
+ }
+
+ @Test
+ public void testGetAllNonStaticFields() {
+ TypeElement type = getType(Model.class);
+
+ List<VariableElement> fields = getAllNonStaticFields(type);
+ assertModelAllFields(fields);
+
+ fields = getAllNonStaticFields(type.asType());
+ assertModelAllFields(fields);
+
+ assertTrue(getAllNonStaticFields((Element) null).isEmpty());
+ assertTrue(getAllNonStaticFields((TypeMirror) null).isEmpty());
+ }
+
+ private void assertModelFields(List<VariableElement> fields) {
+ assertEquals(6, fields.size());
+ assertEquals("d", fields.get(1).getSimpleName().toString());
+ assertEquals("tu", fields.get(2).getSimpleName().toString());
+ assertEquals("str", fields.get(3).getSimpleName().toString());
+ assertEquals("bi", fields.get(4).getSimpleName().toString());
+ assertEquals("bd", fields.get(5).getSimpleName().toString());
+ }
+
+ private void assertModelAllFields(List<VariableElement> fields) {
+ assertEquals(11, fields.size());
+ assertEquals("f", fields.get(0).getSimpleName().toString());
+ assertEquals("d", fields.get(1).getSimpleName().toString());
+ assertEquals("tu", fields.get(2).getSimpleName().toString());
+ assertEquals("str", fields.get(3).getSimpleName().toString());
+ assertEquals("bi", fields.get(4).getSimpleName().toString());
+ assertEquals("bd", fields.get(5).getSimpleName().toString());
+ assertEquals("b", fields.get(6).getSimpleName().toString());
+ assertEquals("s", fields.get(7).getSimpleName().toString());
+ assertEquals("i", fields.get(8).getSimpleName().toString());
+ assertEquals("l", fields.get(9).getSimpleName().toString());
+ assertEquals("z", fields.get(10).getSimpleName().toString());
+ }
+
+ private void testGetDeclaredField(TypeElement type, String fieldName, Type fieldType) {
+ VariableElement field = getDeclaredField(type, fieldName);
+ assertField(field, fieldName, fieldType);
+ }
+
+ private void testFindField(TypeElement type, String fieldName, Type fieldType) {
+ VariableElement field = findField(type, fieldName);
+ assertField(field, fieldName, fieldType);
+ }
+
+ private void assertField(VariableElement field, String fieldName, Type fieldType) {
+ assertEquals(fieldName, field.getSimpleName().toString());
+ assertEquals(fieldType.getTypeName(), field.asType().toString());
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
similarity index 54%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
index b3b27e6..a48b759 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
@@ -14,27 +14,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.util;
import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.warn;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
- * {@link DubboServiceLoader} Test
+ * {@link LoggerUtils} Test
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class LoggerUtilsTest {
+
+ @Test
+ public void testLogger() {
+ assertNotNull(LoggerUtils.LOGGER);
+ }
+
+ @Test
+ public void testInfo() {
+ info("Hello,World");
+ info("Hello,%s", "World");
+ info("%s,%s", "Hello", "World");
+ }
@Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void testWarn() {
+ warn("Hello,World");
+ warn("Hello,%s", "World");
+ warn("%s,%s", "Hello", "World");
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java
new file mode 100644
index 0000000..3d3be6b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getAllDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.hasModifiers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.isPublicNonStatic;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matchParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link MemberUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class MemberUtilsTest extends AbstractAnnotationProcessingTest {
+
+ private TypeElement testType;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ }
+
+ @Override
+ protected void beforeEach() {
+ testType = getType(TestServiceImpl.class);
+ }
+
+ @Test
+ public void testIsPublicNonStatic() {
+ assertFalse(isPublicNonStatic(null));
+ methodsIn(getDeclaredMembers(testType.asType())).forEach(method -> assertTrue(isPublicNonStatic(method)));
+ }
+
+ @Test
+ public void testHasModifiers() {
+ assertFalse(hasModifiers(null));
+ List<? extends Element> members = getAllDeclaredMembers(testType.asType());
+ List<VariableElement> fields = fieldsIn(members);
+ assertTrue(hasModifiers(fields.get(0), PRIVATE));
+ }
+
+ @Test
+ public void testDeclaredMembers() {
+ TypeElement type = getType(Model.class);
+ List<? extends Element> members = getDeclaredMembers(type.asType());
+ List<VariableElement> fields = fieldsIn(members);
+ assertEquals(19, members.size());
+ assertEquals(6, fields.size());
+ assertEquals("f", fields.get(0).getSimpleName().toString());
+ assertEquals("d", fields.get(1).getSimpleName().toString());
+ assertEquals("tu", fields.get(2).getSimpleName().toString());
+ assertEquals("str", fields.get(3).getSimpleName().toString());
+ assertEquals("bi", fields.get(4).getSimpleName().toString());
+ assertEquals("bd", fields.get(5).getSimpleName().toString());
+
+ members = getAllDeclaredMembers(type.asType());
+ fields = fieldsIn(members);
+ assertEquals(11, fields.size());
+ assertEquals("f", fields.get(0).getSimpleName().toString());
+ assertEquals("d", fields.get(1).getSimpleName().toString());
+ assertEquals("tu", fields.get(2).getSimpleName().toString());
+ assertEquals("str", fields.get(3).getSimpleName().toString());
+ assertEquals("bi", fields.get(4).getSimpleName().toString());
+ assertEquals("bd", fields.get(5).getSimpleName().toString());
+ assertEquals("b", fields.get(6).getSimpleName().toString());
+ assertEquals("s", fields.get(7).getSimpleName().toString());
+ assertEquals("i", fields.get(8).getSimpleName().toString());
+ assertEquals("l", fields.get(9).getSimpleName().toString());
+ assertEquals("z", fields.get(10).getSimpleName().toString());
+ }
+
+ @Test
+ public void testMatchParameterTypes() {
+ ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+ assertTrue(matchParameterTypes(method.getParameters(), "java.lang.String"));
+ assertFalse(matchParameterTypes(method.getParameters(), "java.lang.Object"));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.java
new file mode 100644
index 0000000..b2f9162
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getAllDeclaredMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getDeclaredMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getOverrideMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getReturnType;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link MethodUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class MethodUtilsTest extends AbstractAnnotationProcessingTest {
+
+ private TypeElement testType;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ }
+
+ @Override
+ protected void beforeEach() {
+ testType = getType(TestServiceImpl.class);
+ }
+
+ @Test
+ public void testDeclaredMethods() {
+ TypeElement type = getType(Model.class);
+ List<ExecutableElement> methods = getDeclaredMethods(type);
+ assertEquals(12, methods.size());
+
+ methods = getAllDeclaredMethods(type);
+ assertEquals(34, methods.size());
+
+ assertTrue(getAllDeclaredMethods((TypeElement) null).isEmpty());
+ assertTrue(getAllDeclaredMethods((TypeMirror) null).isEmpty());
+ }
+
+ private List<? extends ExecutableElement> doGetAllDeclaredMethods() {
+ return getAllDeclaredMethods(testType, Object.class);
+ }
+
+ @Test
+ public void testGetAllDeclaredMethods() {
+ List<? extends ExecutableElement> methods = doGetAllDeclaredMethods();
+ assertEquals(14, methods.size());
+ }
+
+ @Test
+ public void testGetPublicNonStaticMethods() {
+ List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+ assertEquals(14, methods.size());
+
+ methods = getPublicNonStaticMethods(testType.asType(), Object.class);
+ assertEquals(14, methods.size());
+ }
+
+ @Test
+ public void testIsMethod() {
+ List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+ assertEquals(14, methods.stream().map(MethodUtils::isMethod).count());
+ }
+
+ @Test
+ public void testIsPublicNonStaticMethod() {
+ List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+ assertEquals(14, methods.stream().map(MethodUtils::isPublicNonStaticMethod).count());
+ }
+
+ @Test
+ public void testFindMethod() {
+ TypeElement type = getType(Model.class);
+ // Test methods from java.lang.Object
+ // Object#toString()
+ String methodName = "toString";
+ ExecutableElement method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#hashCode()
+ methodName = "hashCode";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#getClass()
+ methodName = "getClass";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#finalize()
+ methodName = "finalize";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#clone()
+ methodName = "clone";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#notify()
+ methodName = "notify";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#notifyAll()
+ methodName = "notifyAll";
+ method = findMethod(type.asType(), methodName);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#wait(long)
+ methodName = "wait";
+ method = findMethod(type.asType(), methodName, long.class);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#wait(long,int)
+ methodName = "wait";
+ method = findMethod(type.asType(), methodName, long.class, int.class);
+ assertEquals(method.getSimpleName().toString(), methodName);
+
+ // Object#equals(Object)
+ methodName = "equals";
+ method = findMethod(type.asType(), methodName, Object.class);
+ assertEquals(method.getSimpleName().toString(), methodName);
+ }
+
+ @Test
+ public void testGetOverrideMethod() {
+ List<? extends ExecutableElement> methods = doGetAllDeclaredMethods();
+
+ ExecutableElement overrideMethod = getOverrideMethod(processingEnv, testType, methods.get(0));
+ assertNull(overrideMethod);
+
+ ExecutableElement declaringMethod = findMethod(getType(TestService.class), "echo", "java.lang.String");
+
+ overrideMethod = getOverrideMethod(processingEnv, testType, declaringMethod);
+ assertEquals(methods.get(0), overrideMethod);
+ }
+
+ @Test
+ public void testGetMethodName() {
+ ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+ assertEquals("echo", getMethodName(method));
+ assertNull(getMethodName(null));
+ }
+
+ @Test
+ public void testReturnType() {
+ ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+ assertEquals("java.lang.String", getReturnType(method));
+ assertNull(getReturnType(null));
+ }
+
+ @Test
+ public void testMatchParameterTypes() {
+ ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+ assertArrayEquals(new String[]{"java.lang.String"}, getMethodParameterTypes(method));
+ assertTrue(getMethodParameterTypes(null).length == 0);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java
new file mode 100644
index 0000000..a575d4e
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.tools.DefaultTestService;
+import org.apache.dubbo.metadata.tools.GenericTestService;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.GROUP_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.INTERFACE_CLASS_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.INTERFACE_NAME_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.LEGACY_SERVICE_ANNOTATION_TYPE;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SERVICE_ANNOTATION_TYPE;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SUPPORTED_ANNOTATION_TYPES;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.VERSION_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getGroup;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getVersion;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.isServiceAnnotationPresent;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.resolveServiceInterfaceName;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link ServiceAnnotationUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class ServiceAnnotationUtilsTest extends AbstractAnnotationProcessingTest {
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+
+ }
+
+ @Override
+ protected void beforeEach() {
+
+ }
+
+ @Test
+ public void testConstants() {
+ assertEquals("org.apache.dubbo.config.annotation.Service", SERVICE_ANNOTATION_TYPE);
+ assertEquals("com.alibaba.dubbo.config.annotation.Service", LEGACY_SERVICE_ANNOTATION_TYPE);
+ assertEquals("interfaceClass", INTERFACE_CLASS_ATTRIBUTE_NAME);
+ assertEquals("interfaceName", INTERFACE_NAME_ATTRIBUTE_NAME);
+ assertEquals("group", GROUP_ATTRIBUTE_NAME);
+ assertEquals("version", VERSION_ATTRIBUTE_NAME);
+ assertEquals(new HashSet(asList("org.apache.dubbo.config.annotation.Service", "com.alibaba.dubbo.config.annotation.Service")), SUPPORTED_ANNOTATION_TYPES);
+ }
+
+ @Test
+ public void testIsServiceAnnotationPresent() {
+
+ assertTrue(isServiceAnnotationPresent(getType(TestServiceImpl.class)));
+ assertTrue(isServiceAnnotationPresent(getType(GenericTestService.class)));
+ assertTrue(isServiceAnnotationPresent(getType(DefaultTestService.class)));
+
+ assertFalse(isServiceAnnotationPresent(getType(TestService.class)));
+ }
+
+ @Test
+ public void testGetAnnotation() {
+ TypeElement type = getType(TestServiceImpl.class);
+ assertEquals("org.apache.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+ type = getType(GenericTestService.class);
+ assertEquals("com.alibaba.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+ type = getType(DefaultTestService.class);
+ assertEquals("org.apache.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+ assertThrows(IllegalArgumentException.class, () -> getAnnotation(getType(TestService.class)));
+ }
+
+ @Test
+ public void testResolveServiceInterfaceName() {
+ TypeElement type = getType(TestServiceImpl.class);
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+
+ type = getType(GenericTestService.class);
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+
+ type = getType(DefaultTestService.class);
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+ }
+
+ @Test
+ public void testGetVersion() {
+ TypeElement type = getType(TestServiceImpl.class);
+ assertEquals("3.0.0", getVersion(getAnnotation(type)));
+
+ type = getType(GenericTestService.class);
+ assertEquals("2.0.0", getVersion(getAnnotation(type)));
+
+ type = getType(DefaultTestService.class);
+ assertEquals("1.0.0", getVersion(getAnnotation(type)));
+ }
+
+ @Test
+ public void testGetGroup() {
+ TypeElement type = getType(TestServiceImpl.class);
+ assertEquals("test",getGroup(getAnnotation(type)));
+
+ type = getType(GenericTestService.class);
+ assertEquals("generic", getGroup(getAnnotation(type)));
+
+ type = getType(DefaultTestService.class);
+ assertEquals("default", getGroup(getAnnotation(type)));
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java
new file mode 100644
index 0000000..b3d5050
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java
@@ -0,0 +1,467 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.tools.DefaultTestService;
+import org.apache.dubbo.metadata.tools.GenericTestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import java.io.File;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getAllInterfaces;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getAllSuperTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getInterfaces;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResource;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getSuperType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isAnnotationType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isDeclaredType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isInterfaceType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSameType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isTypeElement;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.listDeclaredTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.listTypeElements;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The {@link TypeUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class TypeUtilsTest extends AbstractAnnotationProcessingTest {
+
+ private TypeElement testType;
+
+ @Override
+ protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+ classesToBeCompiled.add(ArrayTypeModel.class);
+ classesToBeCompiled.add(Color.class);
+ }
+
+ @Override
+ protected void beforeEach() {
+ testType = getType(TestServiceImpl.class);
+ }
+
+ @Test
+ public void testIsSimpleType() {
+
+ assertTrue(isSimpleType(getType(Void.class)));
+ assertTrue(isSimpleType(getType(Boolean.class)));
+ assertTrue(isSimpleType(getType(Character.class)));
+ assertTrue(isSimpleType(getType(Byte.class)));
+ assertTrue(isSimpleType(getType(Short.class)));
+ assertTrue(isSimpleType(getType(Integer.class)));
+ assertTrue(isSimpleType(getType(Long.class)));
+ assertTrue(isSimpleType(getType(Float.class)));
+ assertTrue(isSimpleType(getType(Double.class)));
+ assertTrue(isSimpleType(getType(String.class)));
+ assertTrue(isSimpleType(getType(BigDecimal.class)));
+ assertTrue(isSimpleType(getType(BigInteger.class)));
+ assertTrue(isSimpleType(getType(Date.class)));
+
+ assertFalse(isSimpleType(getType(getClass())));
+ assertFalse(isSimpleType((TypeElement) null));
+ assertFalse(isSimpleType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsSameType() {
+ assertTrue(isSameType(getType(Void.class).asType(), "java.lang.Void"));
+ assertFalse(isSameType(getType(String.class).asType(), "java.lang.Void"));
+
+ assertFalse(isSameType(getType(Void.class).asType(), (Type) null));
+ assertFalse(isSameType(null, (Type) null));
+
+ assertFalse(isSameType(getType(Void.class).asType(), (String) null));
+ assertFalse(isSameType(null, (String) null));
+ }
+
+ @Test
+ public void testIsArrayType() {
+ TypeElement type = getType(ArrayTypeModel.class);
+ assertTrue(isArrayType(findField(type.asType(), "integers").asType()));
+ assertTrue(isArrayType(findField(type.asType(), "strings").asType()));
+ assertTrue(isArrayType(findField(type.asType(), "primitiveTypeModels").asType()));
+ assertTrue(isArrayType(findField(type.asType(), "models").asType()));
+ assertTrue(isArrayType(findField(type.asType(), "colors").asType()));
+
+ assertFalse(isArrayType((Element) null));
+ assertFalse(isArrayType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsEnumType() {
+ TypeElement type = getType(Color.class);
+ assertTrue(isEnumType(type.asType()));
+
+ type = getType(ArrayTypeModel.class);
+ assertFalse(isEnumType(type.asType()));
+
+ assertFalse(isEnumType((Element) null));
+ assertFalse(isEnumType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsClassType() {
+ TypeElement type = getType(ArrayTypeModel.class);
+ assertTrue(isClassType(type.asType()));
+
+ type = getType(Model.class);
+ assertTrue(isClassType(type.asType()));
+
+ assertFalse(isClassType((Element) null));
+ assertFalse(isClassType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsPrimitiveType() {
+ TypeElement type = getType(PrimitiveTypeModel.class);
+ getDeclaredFields(type.asType())
+ .stream()
+ .map(VariableElement::asType)
+ .forEach(t -> assertTrue(isPrimitiveType(t)));
+
+ assertFalse(isPrimitiveType(getType(ArrayTypeModel.class)));
+
+ assertFalse(isPrimitiveType((Element) null));
+ assertFalse(isPrimitiveType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsInterfaceType() {
+ TypeElement type = getType(CharSequence.class);
+ assertTrue(isInterfaceType(type));
+ assertTrue(isInterfaceType(type.asType()));
+
+ type = getType(Model.class);
+ assertFalse(isInterfaceType(type));
+ assertFalse(isInterfaceType(type.asType()));
+
+ assertFalse(isInterfaceType((Element) null));
+ assertFalse(isInterfaceType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsAnnotationType() {
+ TypeElement type = getType(Override.class);
+
+ assertTrue(isAnnotationType(type));
+ assertTrue(isAnnotationType(type.asType()));
+
+ type = getType(Model.class);
+ assertFalse(isAnnotationType(type));
+ assertFalse(isAnnotationType(type.asType()));
+
+ assertFalse(isAnnotationType((Element) null));
+ assertFalse(isAnnotationType((TypeMirror) null));
+ }
+
+ @Test
+ public void testGetHierarchicalTypes() {
+ Set hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, true, true);
+ Iterator iterator = hierarchicalTypes.iterator();
+ assertEquals(8, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+ assertEquals("java.lang.Object", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(8, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+ assertEquals("java.lang.Object", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), Object.class);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(7, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, true, false);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(4, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+ assertEquals("java.lang.Object", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, false, true);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(5, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), false, false, true);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(4, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, false, false);
+ iterator = hierarchicalTypes.iterator();
+ assertEquals(1, hierarchicalTypes.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+
+ hierarchicalTypes = getHierarchicalTypes(testType.asType(), false, false, false);
+ assertEquals(0, hierarchicalTypes.size());
+
+ assertTrue(getHierarchicalTypes((TypeElement) null).isEmpty());
+ assertTrue(getHierarchicalTypes((TypeMirror) null).isEmpty());
+ }
+
+
+ @Test
+ public void testGetInterfaces() {
+ TypeElement type = getType(Model.class);
+ List<TypeMirror> interfaces = getInterfaces(type);
+ assertTrue(interfaces.isEmpty());
+
+ interfaces = getInterfaces(testType.asType());
+
+ assertEquals(3, interfaces.size());
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", interfaces.get(0).toString());
+ assertEquals("java.lang.AutoCloseable", interfaces.get(1).toString());
+ assertEquals("java.io.Serializable", interfaces.get(2).toString());
+
+ assertTrue(getInterfaces((TypeElement) null).isEmpty());
+ assertTrue(getInterfaces((TypeMirror) null).isEmpty());
+ }
+
+ @Test
+ public void testGetAllInterfaces() {
+ Set<? extends TypeMirror> interfaces = getAllInterfaces(testType.asType());
+ assertEquals(4, interfaces.size());
+ Iterator<? extends TypeMirror> iterator = interfaces.iterator();
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+ assertEquals("java.io.Serializable", iterator.next().toString());
+ assertEquals("java.util.EventListener", iterator.next().toString());
+
+ Set<TypeElement> allInterfaces = getAllInterfaces(testType);
+ assertEquals(4, interfaces.size());
+
+ Iterator<TypeElement> allIterator = allInterfaces.iterator();
+ assertEquals("org.apache.dubbo.metadata.tools.TestService", allIterator.next().toString());
+ assertEquals("java.lang.AutoCloseable", allIterator.next().toString());
+ assertEquals("java.io.Serializable", allIterator.next().toString());
+ assertEquals("java.util.EventListener", allIterator.next().toString());
+
+ assertTrue(getAllInterfaces((TypeElement) null).isEmpty());
+ assertTrue(getAllInterfaces((TypeMirror) null).isEmpty());
+ }
+
+ @Test
+ public void testGetType() {
+ TypeElement element = TypeUtils.getType(processingEnv, String.class);
+ assertEquals(element, TypeUtils.getType(processingEnv, element.asType()));
+ assertEquals(element, TypeUtils.getType(processingEnv, "java.lang.String"));
+
+ assertNull(TypeUtils.getType(processingEnv, (Type) null));
+ assertNull(TypeUtils.getType(processingEnv, (TypeMirror) null));
+ assertNull(TypeUtils.getType(processingEnv, (CharSequence) null));
+ assertNull(TypeUtils.getType(null, (CharSequence) null));
+ }
+
+ @Test
+ public void testGetSuperType() {
+ TypeElement gtsTypeElement = getSuperType(testType);
+ assertEquals(gtsTypeElement, getType(GenericTestService.class));
+ TypeElement dtsTypeElement = getSuperType(gtsTypeElement);
+ assertEquals(dtsTypeElement, getType(DefaultTestService.class));
+
+ TypeMirror gtsType = getSuperType(testType.asType());
+ assertEquals(gtsType, getType(GenericTestService.class).asType());
+ TypeMirror dtsType = getSuperType(gtsType);
+ assertEquals(dtsType, getType(DefaultTestService.class).asType());
+
+ assertNull(getSuperType((TypeElement) null));
+ assertNull(getSuperType((TypeMirror) null));
+ }
+
+ @Test
+ public void testGetAllSuperTypes() {
+ Set<?> allSuperTypes = getAllSuperTypes(testType);
+ Iterator<?> iterator = allSuperTypes.iterator();
+ assertEquals(3, allSuperTypes.size());
+ assertEquals(iterator.next(), getType(GenericTestService.class));
+ assertEquals(iterator.next(), getType(DefaultTestService.class));
+ assertEquals(iterator.next(), getType(Object.class));
+
+ allSuperTypes = getAllSuperTypes(testType);
+ iterator = allSuperTypes.iterator();
+ assertEquals(3, allSuperTypes.size());
+ assertEquals(iterator.next(), getType(GenericTestService.class));
+ assertEquals(iterator.next(), getType(DefaultTestService.class));
+ assertEquals(iterator.next(), getType(Object.class));
+
+ assertTrue(getAllSuperTypes((TypeElement) null).isEmpty());
+ assertTrue(getAllSuperTypes((TypeMirror) null).isEmpty());
+ }
+
+ @Test
+ public void testIsDeclaredType() {
+ assertTrue(isDeclaredType(testType));
+ assertTrue(isDeclaredType(testType.asType()));
+ assertFalse(isDeclaredType((Element) null));
+ assertFalse(isDeclaredType((TypeMirror) null));
+ assertFalse(isDeclaredType(types.getNullType()));
+ assertFalse(isDeclaredType(types.getPrimitiveType(TypeKind.BYTE)));
+ assertFalse(isDeclaredType(types.getArrayType(types.getPrimitiveType(TypeKind.BYTE))));
+ }
+
+ @Test
+ public void testOfDeclaredType() {
+ assertEquals(testType.asType(), ofDeclaredType(testType));
+ assertEquals(testType.asType(), ofDeclaredType(testType.asType()));
+ assertEquals(ofDeclaredType(testType), ofDeclaredType(testType.asType()));
+
+ assertNull(ofDeclaredType((Element) null));
+ assertNull(ofDeclaredType((TypeMirror) null));
+ }
+
+ @Test
+ public void testIsTypeElement() {
+ assertTrue(isTypeElement(testType));
+ assertTrue(isTypeElement(testType.asType()));
+
+ assertFalse(isTypeElement((Element) null));
+ assertFalse(isTypeElement((TypeMirror) null));
+ }
+
+ @Test
+ public void testOfTypeElement() {
+ assertEquals(testType, ofTypeElement(testType));
+ assertEquals(testType, ofTypeElement(testType.asType()));
+
+ assertNull(ofTypeElement((Element) null));
+ assertNull(ofTypeElement((TypeMirror) null));
+ }
+
+ @Test
+ public void testOfDeclaredTypes() {
+ Set<DeclaredType> declaredTypes = ofDeclaredTypes(asList(getType(String.class), getType(TestServiceImpl.class), getType(Color.class)));
+ assertTrue(declaredTypes.contains(getType(String.class).asType()));
+ assertTrue(declaredTypes.contains(getType(TestServiceImpl.class).asType()));
+ assertTrue(declaredTypes.contains(getType(Color.class).asType()));
+
+ assertTrue(ofDeclaredTypes(null).isEmpty());
+ }
+
+ @Test
+ public void testListDeclaredTypes() {
+ List<DeclaredType> types = listDeclaredTypes(asList(testType, testType, testType));
+ assertEquals(1, types.size());
+ assertEquals(ofDeclaredType(testType), types.get(0));
+
+ types = listDeclaredTypes(asList(new Element[]{null}));
+ assertTrue(types.isEmpty());
+ }
+
+ @Test
+ public void testListTypeElements() {
+ List<TypeElement> typeElements = listTypeElements(asList(testType.asType(), ofDeclaredType(testType)));
+ assertEquals(1, typeElements.size());
+ assertEquals(testType, typeElements.get(0));
+
+ typeElements = listTypeElements(asList(types.getPrimitiveType(TypeKind.BYTE), types.getNullType(), types.getNoType(TypeKind.NONE)));
+ assertTrue(typeElements.isEmpty());
+
+ typeElements = listTypeElements(asList(new TypeMirror[]{null}));
+ assertTrue(typeElements.isEmpty());
+
+ typeElements = listTypeElements(null);
+ assertTrue(typeElements.isEmpty());
+ }
+
+ @Test
+ public void testGetResource() throws URISyntaxException {
+ URL resource = getResource(processingEnv, testType);
+ assertNotNull(resource);
+ assertTrue(new File(resource.toURI()).exists());
+ assertEquals(resource, getResource(processingEnv, testType.asType()));
+ assertEquals(resource, getResource(processingEnv, "org.apache.dubbo.metadata.tools.TestServiceImpl"));
+
+ assertThrows(RuntimeException.class, () -> getResource(processingEnv, "NotFound"));
+ }
+
+ @Test
+ public void testGetResourceName() {
+ assertEquals("java/lang/String.class", getResourceName("java.lang.String"));
+ assertNull(getResourceName(null));
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
index b3b27e6..52ccaf6 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
@@ -14,27 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.Serializable;
/**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
+ * Ancestor
*/
-public class DubboServiceLoaderTest {
+public class Ancestor implements Serializable {
+
+ private boolean z;
+
+ public boolean isZ() {
+ return z;
+ }
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void setZ(boolean z) {
+ this.z = z;
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java
new file mode 100644
index 0000000..a4ee1af
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+import javax.annotation.processing.Processor;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+/**
+ * The Java Compiler
+ */
+public class Compiler {
+
+ private final File sourceDirectory;
+
+ private final JavaCompiler javaCompiler;
+
+ private final StandardJavaFileManager javaFileManager;
+
+ private final Set<Processor> processors = new LinkedHashSet<>();
+
+ public Compiler() throws IOException {
+ this(defaultTargetDirectory());
+ }
+
+ public Compiler(File targetDirectory) throws IOException {
+ this(defaultSourceDirectory(), targetDirectory);
+ }
+
+ public Compiler(File sourceDirectory, File targetDirectory) throws IOException {
+ this.sourceDirectory = sourceDirectory;
+ this.javaCompiler = ToolProvider.getSystemJavaCompiler();
+ this.javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
+ this.javaFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(targetDirectory));
+ this.javaFileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(targetDirectory));
+ }
+
+ private static File defaultSourceDirectory() {
+ return new File(defaultRootDirectory(), "src/test/java");
+ }
+
+ private static File defaultRootDirectory() {
+ return detectClassPath(Compiler.class).getParentFile().getParentFile();
+ }
+
+ private static File defaultTargetDirectory() {
+ File dir = new File(defaultRootDirectory(), "target/generated-classes");
+ dir.mkdirs();
+ return dir;
+ }
+
+ private static File detectClassPath(Class<?> targetClass) {
+ URL classFileURL = targetClass.getProtectionDomain().getCodeSource().getLocation();
+ if ("file".equals(classFileURL.getProtocol())) {
+ return new File(classFileURL.getPath());
+ } else {
+ throw new RuntimeException("No support");
+ }
+ }
+
+ public Compiler processors(Processor... processors) {
+ this.processors.addAll(asList(processors));
+ return this;
+ }
+
+ private Iterable<? extends JavaFileObject> getJavaFileObjects(Class<?>... sourceClasses) {
+ int size = sourceClasses == null ? 0 : sourceClasses.length;
+ File[] javaSourceFiles = new File[size];
+ for (int i = 0; i < size; i++) {
+ File javaSourceFile = javaSourceFile(sourceClasses[i].getName());
+ javaSourceFiles[i] = javaSourceFile;
+ }
+ return javaFileManager.getJavaFileObjects(javaSourceFiles);
+ }
+
+ private File javaSourceFile(String sourceClassName) {
+ String javaSourceFilePath = sourceClassName.replace('.', '/').concat(".java");
+ return new File(sourceDirectory, javaSourceFilePath);
+ }
+
+ public boolean compile(Class<?>... sourceClasses) {
+ JavaCompiler.CompilationTask task = javaCompiler.getTask(null, this.javaFileManager, null,
+ asList("-parameters"),
+// null,
+ null, getJavaFileObjects(sourceClasses));
+ if (!processors.isEmpty()) {
+ task.setProcessors(processors);
+ }
+ return task.call();
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
similarity index 58%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
index b3b27e6..e633e0f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
@@ -14,27 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
/**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
+ * The Compiler test case
*/
-public class DubboServiceLoaderTest {
+public class CompilerTest {
@Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void testCompile() throws IOException {
+ Compiler compiler = new Compiler();
+ compiler.compile(
+ TestServiceImpl.class,
+ DefaultTestService.class,
+ GenericTestService.class);
}
}
+
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java
new file mode 100644
index 0000000..5ac8257
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@link TestService} Implementation
+ *
+ * @since 2.7.5
+ */
+@Service(
+ interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+ version = "1.0.0",
+ group = "default"
+)
+public class DefaultTestService implements TestService {
+
+ private String name;
+
+ @Override
+ public String echo(String message) {
+ return "[ECHO] " + message;
+ }
+
+ @Override
+ public Model model(Model model) {
+ return model;
+ }
+
+ @Override
+ public String testPrimitive(boolean z, int i) {
+ return null;
+ }
+
+ @Override
+ public Model testEnum(TimeUnit timeUnit) {
+ return null;
+ }
+
+ @Override
+ public String testArray(String[] strArray, int[] intArray, Model[] modelArray) {
+ return null;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
index b3b27e6..c60953b 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
@@ -14,27 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
-import java.util.List;
+import com.alibaba.dubbo.config.annotation.Service;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.EventListener;
/**
- * {@link DubboServiceLoader} Test
+ * {@link TestService} Implementation
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+@Service(
+ version = "2.0.0",
+ group = "generic"
+)
+public class GenericTestService extends DefaultTestService implements TestService, EventListener {
+ @Override
+ public String echo(String message) {
+ return "[ECHO] " + message;
}
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
index b3b27e6..4273a0f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
@@ -14,27 +14,50 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
+/**
+ * Parent
+ */
+public class Parent extends Ancestor {
-import java.util.List;
+ private byte b;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+ private short s;
-/**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
- */
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ private int i;
+
+ private long l;
+
+ public byte getB() {
+ return b;
+ }
+
+ public void setB(byte b) {
+ this.b = b;
+ }
+
+ public short getS() {
+ return s;
+ }
+
+ public void setS(short s) {
+ this.s = s;
+ }
+
+ public int getI() {
+ return i;
+ }
+
+ public void setI(int i) {
+ this.i = i;
+ }
+
+ public long getL() {
+ return l;
+ }
+
+ public void setL(long l) {
+ this.l = l;
}
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
index b3b27e6..8db18d7 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
@@ -14,27 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.Map;
/**
- * {@link DubboServiceLoader} Test
+ * An interface for REST service
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
+public interface RestService {
+
+ String param(String param);
+
+ String params(int a, String b);
+
+ String headers(String header, String header2, Integer param);
+
+ String pathVariables(String path1, String path2, String param);
+
+ String form(String form);
+
+ User requestBodyMap(Map<String, Object> data, String param);
+
+ Map<String, Object> requestBodyUser(User user);
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
index b3b27e6..3e318d2 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
@@ -14,27 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
/**
- * {@link DubboServiceLoader} Test
+ * {@link RestService} Test
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class RestServiceTest {
@Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void test() throws IOException {
+ Compiler compiler = new Compiler();
+ compiler.compile(User.class, RestService.class,
+ StandardRestService.class,
+ SpringRestService.class);
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestService.java
new file mode 100644
index 0000000..c684cb3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestService.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Spring MVC {@link RestService}
+ *
+ * @since 2.7.5
+ */
+@Service(version = "2.0.0")
+@RestController
+public class SpringRestService implements RestService {
+
+ @Override
+ @GetMapping(value = "/param")
+ public String param(@RequestParam(defaultValue = "value-param") String param) {
+ return param;
+ }
+
+ @Override
+ @PostMapping("/params")
+ public String params(@RequestParam(defaultValue = "value-a") int a, @RequestParam(defaultValue = "value-b") String b) {
+ return a + b;
+ }
+
+ @Override
+ @GetMapping("/headers")
+ public String headers(@RequestHeader(name = "h", defaultValue = "value-h") String header,
+ @RequestHeader(name = "h2", defaultValue = "value-h2") String header2,
+ @RequestParam(value = "v", defaultValue = "1") Integer param) {
+ String result = header + " , " + header2 + " , " + param;
+ return result;
+ }
+
+ @Override
+ @GetMapping("/path-variables/{p1}/{p2}")
+ public String pathVariables(@PathVariable("p1") String path1,
+ @PathVariable("p2") String path2, @RequestParam("v") String param) {
+ String result = path1 + " , " + path2 + " , " + param;
+ return result;
+ }
+
+ @Override
+ @PostMapping("/form")
+ public String form(@RequestParam("f") String form) {
+ return String.valueOf(form);
+ }
+
+ @Override
+ @PostMapping(value = "/request/body/map", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public User requestBodyMap(@RequestBody Map<String, Object> data,
+ @RequestParam("param") String param) {
+ User user = new User();
+ user.setId(((Integer) data.get("id")).longValue());
+ user.setName((String) data.get("name"));
+ user.setAge((Integer) data.get("age"));
+ return user;
+ }
+
+ @PostMapping(value = "/request/body/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @Override
+ public Map<String, Object> requestBodyUser(@RequestBody User user) {
+ Map<String, Object> map = new HashMap<>();
+ map.put("id", user.getId());
+ map.put("name", user.getName());
+ map.put("age", user.getAge());
+ return map;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
index b3b27e6..d240da1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
@@ -14,27 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
/**
- * {@link DubboServiceLoader} Test
+ * {@link SpringRestService} Test
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class SpringRestServiceTest {
@Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void test() throws IOException {
+ Compiler compiler = new Compiler();
+ compiler.compile(User.class, RestService.class, SpringRestService.class);
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestService.java
new file mode 100644
index 0000000..064f28c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestService.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * JAX-RS {@link RestService}
+ */
+@Service(version = "3.0.0", protocol = {"dubbo", "rest"})
+@Path("/")
+public class StandardRestService implements RestService {
+
+ @Override
+ @Path("param")
+ @GET
+ public String param(@QueryParam("param") String param) {
+ return param;
+ }
+
+ @Override
+ @Path("params")
+ @POST
+ public String params(@QueryParam("a") int a, @QueryParam("b") String b) {
+ return a + b;
+ }
+
+ @Override
+ @Path("headers")
+ @GET
+ public String headers(@HeaderParam("h") String header,
+ @HeaderParam("h2") String header2, @QueryParam("v") Integer param) {
+ String result = header + " , " + header2 + " , " + param;
+ return result;
+ }
+
+ @Override
+ @Path("path-variables/{p1}/{p2}")
+ @GET
+ public String pathVariables(@PathParam("p1") String path1,
+ @PathParam("p2") String path2, @QueryParam("v") String param) {
+ String result = path1 + " , " + path2 + " , " + param;
+ return result;
+ }
+
+ // @CookieParam does not support : https://github.com/OpenFeign/feign/issues/913
+ // @CookieValue also does not support
+
+ @Override
+ @Path("form")
+ @POST
+ public String form(@FormParam("f") String form) {
+ return String.valueOf(form);
+ }
+
+ @Override
+ @Path("request/body/map")
+ @POST
+ @Produces("application/json;charset=UTF-8")
+ public User requestBodyMap(Map<String, Object> data,
+ @QueryParam("param") String param) {
+ User user = new User();
+ user.setId(((Integer) data.get("id")).longValue());
+ user.setName((String) data.get("name"));
+ user.setAge((Integer) data.get("age"));
+ return user;
+ }
+
+ @Path("request/body/user")
+ @POST
+ @Override
+ @Consumes("application/json;charset=UTF-8")
+ public Map<String, Object> requestBodyUser(User user) {
+ Map<String, Object> map = new HashMap<>();
+ map.put("id", user.getId());
+ map.put("name", user.getName());
+ map.put("age", user.getAge());
+ return map;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
index b3b27e6..8eab99e 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
@@ -14,27 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
import org.junit.jupiter.api.Test;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
/**
- * {@link DubboServiceLoader} Test
+ * The test case for {@link StandardRestService}
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+public class StandardRestServiceTest {
@Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ public void test() throws IOException {
+ Compiler compiler = new Compiler();
+ compiler.compile(User.class, RestService.class, StandardRestService.class);
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java
new file mode 100644
index 0000000..58a6004
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * {@link Processor} for test
+ *
+ * @since 2.7.5
+ */
+@SupportedAnnotationTypes("*")
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+public class TestProcessor extends AbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return false;
+ }
+
+ public ProcessingEnvironment getProcessingEnvironment() {
+ return super.processingEnv;
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
similarity index 51%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
index b3b27e6..d397b3f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
@@ -14,27 +14,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import java.util.concurrent.TimeUnit;
/**
- * {@link DubboServiceLoader} Test
+ * Test Service
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
-
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
- }
+@Path("/echo")
+public interface TestService {
+
+ @GET
+ <T> String echo(@PathParam("message") @DefaultValue("mercyblitz") String message);
+
+ @POST
+ Model model(@PathParam("model") Model model);
+
+ // Test primitive
+ @PUT
+ String testPrimitive(boolean z, int i);
+
+ // Test enumeration
+ @PUT
+ Model testEnum(TimeUnit timeUnit);
+
+ // Test Array
+ @GET
+ String testArray(String[] strArray, int[] intArray, Model[] modelArray);
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
similarity index 50%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
index b3b27e6..aeb4530 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
@@ -14,27 +14,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
-import org.junit.jupiter.api.Test;
-import java.util.List;
+import org.apache.dubbo.config.annotation.Service;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.Serializable;
/**
- * {@link DubboServiceLoader} Test
+ * {@link TestService} Implementation
*
* @since 2.7.5
*/
-public class DubboServiceLoaderTest {
+@com.alibaba.dubbo.config.annotation.Service(
+ interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+ interfaceClass = TestService.class,
+ version = "3.0.0",
+ group = "test"
+)
+@Service(
+ interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+ interfaceClass = TestService.class,
+ version = "3.0.0",
+ group = "test"
+)
+public class TestServiceImpl extends GenericTestService implements TestService, AutoCloseable, Serializable {
- @Test
- public void testLoad() {
- List<CharSequence> charSequences = loadServices(CharSequence.class);
- assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
- assertEquals(String.class, charSequences.get(1).getClass());
- assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+ @Override
+ public String echo(String message) {
+ return "[ECHO] " + message;
+ }
+
+ @Override
+ public void close() throws Exception {
}
}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/User.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/User.java
new file mode 100644
index 0000000..e79f7c4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/User.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+import java.io.Serializable;
+
+/**
+ * User Entity
+ *
+ * @since 2.7.5
+ */
+public class User implements Serializable {
+
+ private Long id;
+
+ private String name;
+
+ private Integer age;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
+ }
+}
diff --git a/dubbo-metadata/pom.xml b/dubbo-metadata/pom.xml
index fefa364..17ceada 100644
--- a/dubbo-metadata/pom.xml
+++ b/dubbo-metadata/pom.xml
@@ -35,6 +35,7 @@
<module>dubbo-metadata-report-consul</module>
<module>dubbo-metadata-report-etcd</module>
<module>dubbo-metadata-report-nacos</module>
+ <module>dubbo-metadata-processor</module>
</modules>
</project>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index 4f8363d..7132c32 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.DubboServiceLoader;
+import org.apache.dubbo.common.utils.PrioritizedServiceLoader;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.ServiceNameMapping;
@@ -77,7 +77,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
import static org.apache.dubbo.common.function.ThrowableAction.execute;
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
import static org.apache.dubbo.metadata.MetadataService.toURLs;
import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension;
@@ -190,10 +190,10 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
/**
* Initialize {@link SubscribedURLsSynthesizer} instances that are
- * {@link DubboServiceLoader#loadServices(Class, ClassLoader) loaded} by {@link DubboServiceLoader}
+ * {@link PrioritizedServiceLoader#loadServices(Class, ClassLoader) loaded} by {@link PrioritizedServiceLoader}
*
* @return non-null {@link List}
- * @see DubboServiceLoader#loadServices(Class, ClassLoader)
+ * @see PrioritizedServiceLoader#loadServices(Class, ClassLoader)
*/
private List<SubscribedURLsSynthesizer> initSubscribedURLsSynthesizers() {
return loadServices(SubscribedURLsSynthesizer.class, this.getClass().getClassLoader());
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
index 68abcdb..e5d613c 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
import java.util.ServiceLoader;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.load;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
... 1 lines suppressed ...