2.7.6 REST Metadata (#5738)
* Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring * Polish /apache/dubbo#4674 & /apache/dubbo#4470 * Polish /apache/dubbo#5093 : Revert the previous commit * Polish apache/dubbo#5093 : [Feature] Dubbo Services generate the metadata of REST services * Polish apache/dubbo#5306 : [Migration] Upgrade the @since tags in Javadoc migration cloud native to master * Polish apache/dubbo#5306 : [Migration] Upgrade the @since tags in Javadoc migration cloud native to master * Polish apache/dubbo#5309 : [ISSURE] The beans of Dubbo's Config can't be found on the ReferenceBean's initialization * Polish apache/dubbo#5312 : Resolve the demos' issues of zookeeper and nacos * Polish apache/dubbo#5313 : [Migration] migrate the code in common module from cloud-native branch to master * Polish apache/dubbo#5316 : [Refactor] Replace @EnableDubboConfigBinding Using spring-context-support * Polish apache/dubbo#5317 : [Refactor] Refactor ReferenceAnnotationBeanPostProcessor using Alibaba spring-context-suuport API * Polish apache/dubbo#5321 : Remove BeanFactoryUtils * Polish apache/dubbo#5321 : Remove AnnotatedBeanDefinitionRegistryUtils * Polish apache/dubbo#5321 : Remove AnnotationUtils * Polish apache/dubbo#5321 : Remove ClassUtils * Polish apache/dubbo#5321 : Remove BeanRegistrar * Polish apache/dubbo#5321 : Remove ObjectUtils * Polish apache/dubbo#5321 : Remove PropertySourcesUtils * Polish apache/dubbo#5325 : [Migration] To migrate dubbo-metadata-api from cloud-native branch * Polish apache/dubbo#5326 : [Migration] To migrate dubbo-metadata-processor from cloud-native branch * Polish apache/dubbo#5329 : [Feature] To add the default metadata into ServiceInstance * Polish apache/dubbo#5339 : [Refactor] Refactor the DynamicConfiguration interface * Polish bugfix * Fixes test cases * Merge remote-tracking branch 'upstream/master' into cloud-native-2.7.5 # Conflicts: # dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java # dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java * Merge remote-tracking branch 'upstream/master' into cloud-native-2.7.5 # Conflicts: # dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java # dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java * Polish /apache/dubbo#5721 : [Enhancement] Setting the default IDs for Dubbo's Config Beans * Polish /apache/dubbo#5729 : [Optimization] To remove EnableDubboConfigBinding and EnableDubboConfigBindings * Polish /apache/dubbo#5594 : [Feature] Add the resolver of ServiceRestMetadata based on Java Reflection * Polish /apache/dubbo#5736 : [Feature] Introducing Conversion features * Polish /apache/dubbo#5737 : [Feature] Introducing "dubbo-metadata-processor" module * Polish /apache/dubbo#5594 : Change the Metadata implementation * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases * Polish /apache/dubbo#5594 : Fixed test cases
This commit is contained in:
parent
d30ca86395
commit
7b0ae127a9
|
|
@ -14,7 +14,8 @@
|
|||
See the License for the specific language governing permissions and
|
||||
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>
|
||||
|
|
@ -685,172 +686,218 @@
|
|||
</artifactSet>
|
||||
<transformers>
|
||||
<!-- dubbo-common beginning -->
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.infra.InfraAdapter
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.store.DataStore
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool
|
||||
</resource>
|
||||
</transformer>
|
||||
<!-- dubbo-common end -->
|
||||
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Codec2</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Transporter</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.exchange.Exchanger
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.http.HttpBinder
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.p2p.Networker
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.InvokerListener</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.ExporterListener</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.container.Container</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.monitor.MonitorFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.validation.Validation</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<!-- @since 2.7.5 -->
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.event.EventDispatcher
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
|
|
@ -871,6 +918,56 @@
|
|||
</resource>
|
||||
</transformer>
|
||||
|
||||
<!-- @since 2.7.6 -->
|
||||
|
||||
<!-- 'dubbo-common' module -->
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.convert.Converter
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.convert.multiple.MultiValueConverter
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
<!-- 'dubbo-metadata-api' module -->
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
<!-- 'dubbo-metadata-processor' module -->
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataResolver
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.extension.ExtensionLoader;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.common.lang.Prioritized;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
|
||||
|
||||
/**
|
||||
* A class to convert the source-typed value to the target-typed value
|
||||
*
|
||||
* @param <S> The source type
|
||||
* @param <T> The target type
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@SPI
|
||||
@FunctionalInterface
|
||||
public interface Converter<S, T> extends Prioritized {
|
||||
|
||||
/**
|
||||
* Accept the source type and target type or not
|
||||
*
|
||||
* @param sourceType the source type
|
||||
* @param targetType the target type
|
||||
* @return if accepted, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
default boolean accept(Class<?> sourceType, Class<?> targetType) {
|
||||
return isAssignableFrom(sourceType, getSourceType()) && isAssignableFrom(targetType, getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the source-typed value to the target-typed value
|
||||
*
|
||||
* @param source the source-typed value
|
||||
* @return the target-typed value
|
||||
*/
|
||||
T convert(S source);
|
||||
|
||||
/**
|
||||
* Get the source type
|
||||
*
|
||||
* @return non-null
|
||||
*/
|
||||
default Class<S> getSourceType() {
|
||||
return findActualTypeArgument(getClass(), Converter.class, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target type
|
||||
*
|
||||
* @return non-null
|
||||
*/
|
||||
default Class<T> getTargetType() {
|
||||
return findActualTypeArgument(getClass(), Converter.class, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Converter instance from {@link ExtensionLoader} with the specified source and target type
|
||||
*
|
||||
* @param sourceType the source type
|
||||
* @param targetType the target type
|
||||
* @return
|
||||
* @see ExtensionLoader#getSupportedExtensionInstances()
|
||||
*/
|
||||
static Converter<?, ?> getConverter(Class<?> sourceType, Class<?> targetType) {
|
||||
return getExtensionLoader(Converter.class)
|
||||
.getSupportedExtensionInstances()
|
||||
.stream()
|
||||
.filter(converter -> converter.accept(sourceType, targetType))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A class to covert {@link String} to the target-typed value
|
||||
*
|
||||
* @see Converter
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface StringConverter<T> extends Converter<String, T> {
|
||||
}
|
||||
|
|
@ -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.common.convert;
|
||||
|
||||
import static java.lang.Boolean.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Boolean}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBooleanConverter implements StringConverter<Boolean> {
|
||||
|
||||
@Override
|
||||
public Boolean convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 5;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to <code>char[]</code>
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCharArrayConverter implements StringConverter<char[]> {
|
||||
|
||||
@Override
|
||||
public char[] convert(String source) {
|
||||
return isNotEmpty(source) ? source.toCharArray() : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 7;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
import static org.apache.dubbo.common.utils.StringUtils.length;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Character}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCharacterConverter implements StringConverter<Character> {
|
||||
|
||||
@Override
|
||||
public Character convert(String source) {
|
||||
int length = length(source);
|
||||
if (length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (length > 1) {
|
||||
throw new IllegalArgumentException("The source String is more than one character!");
|
||||
}
|
||||
return source.charAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 8;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
import static java.lang.Double.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Double}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToDoubleConverter implements StringConverter<Double> {
|
||||
|
||||
@Override
|
||||
public Double convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 3;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.common.convert;
|
||||
|
||||
import static java.lang.Float.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Float}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToFloatConverter implements StringConverter<Float> {
|
||||
|
||||
@Override
|
||||
public Float convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.common.convert;
|
||||
|
||||
import static java.lang.Integer.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Integer}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToIntegerConverter implements StringConverter<Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
import static java.lang.Long.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Long}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToLongConverter implements StringConverter<Long> {
|
||||
|
||||
@Override
|
||||
public Long convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Optional}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToOptionalConverter implements StringConverter<Optional> {
|
||||
|
||||
@Override
|
||||
public Optional convert(String source) {
|
||||
return ofNullable(source);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return MIN_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert;
|
||||
|
||||
import static java.lang.Short.valueOf;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Short}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToShortConverter implements StringConverter<Short> {
|
||||
|
||||
@Override
|
||||
public Short convert(String source) {
|
||||
return isNotEmpty(source) ? valueOf(source) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return NORMAL_PRIORITY + 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A class to covert {@link String} to {@link String} value, just no-op
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToStringConverter implements StringConverter<String> {
|
||||
|
||||
@Override
|
||||
public String convert(String source) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.common.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.common.lang.Prioritized;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
|
||||
|
||||
/**
|
||||
* An interface to convert the source-typed value to multiple value, e.g , Java array, {@link Collection} or
|
||||
* sub-interfaces
|
||||
*
|
||||
* @param <S> The source type
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@SPI
|
||||
public interface MultiValueConverter<S> extends Prioritized {
|
||||
|
||||
/**
|
||||
* Accept the source type and target type or not
|
||||
*
|
||||
* @param sourceType the source type
|
||||
* @param multiValueType the multi-value type
|
||||
* @return if accepted, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
boolean accept(Class<S> sourceType, Class<?> multiValueType);
|
||||
|
||||
/**
|
||||
* Convert the source to be the multiple value
|
||||
*
|
||||
* @param source the source-typed value
|
||||
* @param multiValueType the multi-value type
|
||||
* @param elementType the element type
|
||||
* @return
|
||||
*/
|
||||
Object convert(S source, Class<?> multiValueType, Class<?> elementType);
|
||||
|
||||
/**
|
||||
* Get the source type
|
||||
*
|
||||
* @return non-null
|
||||
*/
|
||||
default Class<S> getSourceType() {
|
||||
return findActualTypeArgument(getClass(), MultiValueConverter.class, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.common.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import static java.lang.reflect.Array.newInstance;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to array-type object
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToArrayConverter implements StringToMultiValueConverter {
|
||||
|
||||
public boolean accept(Class<String> type, Class<?> multiValueType) {
|
||||
if (multiValueType != null && multiValueType.isArray()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(String[] segments, int size, Class<?> targetType, Class<?> elementType) {
|
||||
|
||||
Class<?> componentType = targetType.getComponentType();
|
||||
|
||||
Converter converter = Converter.getConverter(String.class, componentType);
|
||||
|
||||
Object array = newInstance(componentType, size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Array.set(array, i, converter.convert(segments[i]));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return MIN_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link BlockingDeque}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBlockingDequeConverter extends StringToIterableConverter<BlockingDeque> {
|
||||
|
||||
@Override
|
||||
protected BlockingDeque createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new LinkedBlockingDeque(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link BlockingDeque}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBlockingQueueConverter extends StringToIterableConverter<BlockingQueue> {
|
||||
|
||||
@Override
|
||||
protected BlockingQueue createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new ArrayBlockingQueue(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Collection}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCollectionConverter extends StringToIterableConverter<Collection> {
|
||||
|
||||
@Override
|
||||
protected Collection createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new ArrayList(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Deque}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToDequeConverter extends StringToIterableConverter<Deque> {
|
||||
|
||||
@Override
|
||||
protected Deque createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new ArrayDeque(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.StringConverter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.convert.Converter.getConverter;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Iterable}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public abstract class StringToIterableConverter<T extends Iterable> implements StringToMultiValueConverter {
|
||||
|
||||
public boolean accept(Class<String> type, Class<?> multiValueType) {
|
||||
return isAssignableFrom(getSupportedType(), multiValueType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object convert(String[] segments, int size, Class<?> multiValueType, Class<?> elementType) {
|
||||
|
||||
Optional<StringConverter> stringConverter = getStringConverter(elementType);
|
||||
|
||||
return stringConverter.map(converter -> {
|
||||
|
||||
T convertedObject = createMultiValue(size, multiValueType);
|
||||
|
||||
if (convertedObject instanceof Collection) {
|
||||
Collection collection = (Collection) convertedObject;
|
||||
for (int i = 0; i < size; i++) {
|
||||
String segment = segments[i];
|
||||
Object element = converter.convert(segment);
|
||||
collection.add(element);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
return convertedObject;
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
protected abstract T createMultiValue(int size, Class<?> multiValueType);
|
||||
|
||||
protected Optional<StringConverter> getStringConverter(Class<?> elementType) {
|
||||
StringConverter converter = (StringConverter) getConverter(String.class, elementType);
|
||||
return Optional.ofNullable(converter);
|
||||
}
|
||||
|
||||
protected final Class<T> getSupportedType() {
|
||||
return findActualTypeArgument(getClass(), StringToIterableConverter.class, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getPriority() {
|
||||
int level = getAllInterfaces(getSupportedType(), type ->
|
||||
isAssignableFrom(Iterable.class, type)).size();
|
||||
return MIN_PRIORITY - level;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link List}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToListConverter extends StringToIterableConverter<List> {
|
||||
|
||||
@Override
|
||||
protected List createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new ArrayList(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.common.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.split;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to multiple value object
|
||||
*
|
||||
* @see MultiValueConverter
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface StringToMultiValueConverter extends MultiValueConverter<String> {
|
||||
|
||||
@Override
|
||||
default Object convert(String source, Class<?> multiValueType, Class<?> elementType) {
|
||||
|
||||
if (isEmpty(source)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// split by the comma
|
||||
String[] segments = split(source, ',');
|
||||
|
||||
if (ArrayUtils.isEmpty(segments)) { // If empty array, create an array with only one element
|
||||
segments = new String[]{source};
|
||||
}
|
||||
|
||||
int size = segments.length;
|
||||
|
||||
return convert(segments, size, multiValueType, elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the segments to multiple value object
|
||||
*
|
||||
* @param segments the String array of content
|
||||
* @param size the size of multiple value object
|
||||
* @param targetType the target type
|
||||
* @param elementType the element type
|
||||
* @return multiple value object
|
||||
*/
|
||||
Object convert(String[] segments, int size, Class<?> targetType, Class<?> elementType);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.NavigableSet;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link SortedSet}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToNavigableSetConverter extends StringToIterableConverter<NavigableSet> {
|
||||
|
||||
@Override
|
||||
protected NavigableSet createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new TreeSet();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Deque}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToQueueConverter extends StringToIterableConverter<Queue> {
|
||||
|
||||
@Override
|
||||
protected Queue createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new ArrayDeque(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link Set}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToSetConverter extends StringToIterableConverter<Set> {
|
||||
|
||||
@Override
|
||||
protected Set createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new HashSet(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link SortedSet}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToSortedSetConverter extends StringToIterableConverter<SortedSet> {
|
||||
|
||||
@Override
|
||||
protected SortedSet createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new TreeSet();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.convert.multiple;
|
||||
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
/**
|
||||
* The class to convert {@link String} to {@link TransferQueue}-based value
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToTransferQueueConverter extends StringToIterableConverter<TransferQueue> {
|
||||
|
||||
@Override
|
||||
protected TransferQueue createMultiValue(int size, Class<?> multiValueType) {
|
||||
return new LinkedTransferQueue();
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.common.extension;
|
|||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.context.Lifecycle;
|
||||
import org.apache.dubbo.common.extension.support.ActivateComparator;
|
||||
import org.apache.dubbo.common.lang.Prioritized;
|
||||
import org.apache.dubbo.common.logger.Logger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||
|
|
@ -40,7 +41,8 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -49,6 +51,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.Collections.sort;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX;
|
||||
|
|
@ -442,14 +445,16 @@ public class ExtensionLoader<T> {
|
|||
}
|
||||
|
||||
public Set<T> getSupportedExtensionInstances() {
|
||||
Set<T> instances = new HashSet<>();
|
||||
List<T> instances = new LinkedList<>();
|
||||
Set<String> supportedExtensions = getSupportedExtensions();
|
||||
if (CollectionUtils.isNotEmpty(supportedExtensions)) {
|
||||
for (String name : supportedExtensions) {
|
||||
instances.add(getExtension(name));
|
||||
}
|
||||
}
|
||||
return instances;
|
||||
// sort the Prioritized instances
|
||||
sort(instances, Prioritized.COMPARATOR);
|
||||
return new LinkedHashSet<>(instances);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.apache.dubbo.common.function.Predicates.and;
|
||||
import static org.apache.dubbo.common.function.Streams.filterAll;
|
||||
import static org.apache.dubbo.common.function.Streams.filterFirst;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllInheritedTypes;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
|
||||
import static org.apache.dubbo.common.utils.CollectionUtils.first;
|
||||
import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
|
||||
|
||||
/**
|
||||
* Commons Annotation Utilities class
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface AnnotationUtils {
|
||||
|
||||
/**
|
||||
* Resolve the annotation type by the annotated element and resolved class name
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationClassName the class name of annotation
|
||||
* @param <A> the type of annotation
|
||||
* @return If resolved, return the type of annotation, or <code>null</code>
|
||||
*/
|
||||
static <A extends Annotation> Class<A> resolveAnnotationType(AnnotatedElement annotatedElement,
|
||||
String annotationClassName) {
|
||||
ClassLoader classLoader = annotatedElement.getClass().getClassLoader();
|
||||
Class<?> annotationType = resolveClass(annotationClassName, classLoader);
|
||||
if (annotationType == null || !Annotation.class.isAssignableFrom(annotationType)) {
|
||||
return null;
|
||||
}
|
||||
return (Class<A>) annotationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified type a generic {@link Class type}
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @return if <code>annotatedElement</code> is the {@link Class}, return <code>true</code>, or <code>false</code>
|
||||
* @see ElementType#TYPE
|
||||
*/
|
||||
static boolean isType(AnnotatedElement annotatedElement) {
|
||||
return annotatedElement instanceof Class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the type of specified annotation same to the expected type?
|
||||
*
|
||||
* @param annotation the specified {@link Annotation}
|
||||
* @param annotationType the expected annotation type
|
||||
* @return if same, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isSameType(Annotation annotation, Class<? extends Annotation> annotationType) {
|
||||
if (annotation == null || annotationType == null) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(annotation.annotationType(), annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an instance of {@link Predicate} to excluded annotation type
|
||||
*
|
||||
* @param excludedAnnotationType excluded annotation type
|
||||
* @return non-null
|
||||
*/
|
||||
static Predicate<Annotation> excludedType(Class<? extends Annotation> excludedAnnotationType) {
|
||||
return annotation -> !isSameType(annotation, excludedAnnotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attribute from the specified {@link Annotation annotation}
|
||||
*
|
||||
* @param annotation the specified {@link Annotation annotation}
|
||||
* @param attributeName the attribute name
|
||||
* @param <T> the type of attribute
|
||||
* @return the attribute value
|
||||
* @throws IllegalArgumentException If the attribute name can't be found
|
||||
*/
|
||||
static <T> T getAttribute(Annotation annotation, String attributeName) throws IllegalArgumentException {
|
||||
return annotation == null ? null : invokeMethod(annotation, attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "value" attribute from the specified {@link Annotation annotation}
|
||||
*
|
||||
* @param annotation the specified {@link Annotation annotation}
|
||||
* @param <T> the type of attribute
|
||||
* @return the value of "value" attribute
|
||||
* @throws IllegalArgumentException If the attribute name can't be found
|
||||
*/
|
||||
static <T> T getValue(Annotation annotation) throws IllegalArgumentException {
|
||||
return getAttribute(annotation, "value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Annotation} from the specified {@link AnnotatedElement the annotated element} and
|
||||
* {@link Annotation annotation} class name
|
||||
*
|
||||
* @param annotatedElement {@link AnnotatedElement}
|
||||
* @param annotationClassName the class name of annotation
|
||||
* @param <A> The type of {@link Annotation}
|
||||
* @return the {@link Annotation} if found
|
||||
* @throws ClassCastException If the {@link Annotation annotation} type that client requires can't match actual type
|
||||
*/
|
||||
static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, String annotationClassName)
|
||||
throws ClassCastException {
|
||||
Class<? extends Annotation> annotationType = resolveAnnotationType(annotatedElement, annotationClassName);
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
return (A) annotatedElement.getAnnotation(annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get annotations that are <em>directly present</em> on this element.
|
||||
* This method ignores inherited annotations.
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationsToFilter the annotations to filter
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<Annotation> getDeclaredAnnotations(AnnotatedElement annotatedElement,
|
||||
Predicate<Annotation>... annotationsToFilter) {
|
||||
if (annotatedElement == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
return unmodifiableList(filterAll(asList(annotatedElement.getDeclaredAnnotations()), annotationsToFilter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all directly declared annotations of the the annotated element, not including
|
||||
* meta annotations.
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationsToFilter the annotations to filter
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<Annotation> getAllDeclaredAnnotations(AnnotatedElement annotatedElement,
|
||||
Predicate<Annotation>... annotationsToFilter) {
|
||||
if (isType(annotatedElement)) {
|
||||
return getAllDeclaredAnnotations((Class) annotatedElement, annotationsToFilter);
|
||||
} else {
|
||||
return getDeclaredAnnotations(annotatedElement, annotationsToFilter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all directly declared annotations of the specified type and its' all hierarchical types, not including
|
||||
* meta annotations.
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param annotationsToFilter the annotations to filter
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<Annotation> getAllDeclaredAnnotations(Class<?> type, Predicate<Annotation>... annotationsToFilter) {
|
||||
|
||||
if (type == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<Annotation> allAnnotations = new LinkedList<>();
|
||||
|
||||
// All types
|
||||
Set<Class<?>> allTypes = new LinkedHashSet<>();
|
||||
// Add current type
|
||||
allTypes.add(type);
|
||||
// Add all inherited types
|
||||
allTypes.addAll(getAllInheritedTypes(type, t -> !Object.class.equals(t)));
|
||||
|
||||
for (Class<?> t : allTypes) {
|
||||
allAnnotations.addAll(getDeclaredAnnotations(t, annotationsToFilter));
|
||||
}
|
||||
|
||||
return unmodifiableList(allAnnotations);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the meta-annotated {@link Annotation annotations} directly, excluding {@link Target}, {@link Retention}
|
||||
* and {@link Documented}
|
||||
*
|
||||
* @param annotationType the {@link Annotation annotation} type
|
||||
* @param metaAnnotationsToFilter the meta annotations to filter
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<Annotation> getMetaAnnotations(Class<? extends Annotation> annotationType,
|
||||
Predicate<Annotation>... metaAnnotationsToFilter) {
|
||||
return getDeclaredAnnotations(annotationType,
|
||||
// Excludes the Java native annotation types or it causes the stack overflow, e.g,
|
||||
// @Target annotates itself
|
||||
excludedType(Target.class),
|
||||
excludedType(Retention.class),
|
||||
excludedType(Documented.class),
|
||||
// Add other predicates
|
||||
and(metaAnnotationsToFilter)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all meta annotations from the specified {@link Annotation annotation} type
|
||||
*
|
||||
* @param annotationType the {@link Annotation annotation} type
|
||||
* @param annotationsToFilter the annotations to filter
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<Annotation> getAllMetaAnnotations(Class<? extends Annotation> annotationType,
|
||||
Predicate<Annotation>... annotationsToFilter) {
|
||||
|
||||
List<Annotation> allMetaAnnotations = new LinkedList<>();
|
||||
|
||||
List<Annotation> metaAnnotations = getMetaAnnotations(annotationType);
|
||||
|
||||
allMetaAnnotations.addAll(metaAnnotations);
|
||||
|
||||
for (Annotation metaAnnotation : metaAnnotations) {
|
||||
// Get the nested meta annotations recursively
|
||||
allMetaAnnotations.addAll(getAllMetaAnnotations(metaAnnotation.annotationType()));
|
||||
}
|
||||
|
||||
return unmodifiableList(filterAll(allMetaAnnotations, annotationsToFilter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the annotation that is annotated on the specified element may be a meta-annotation
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationClassName the class name of annotation
|
||||
* @param <A> the required type of annotation
|
||||
* @return If found, return first matched-type {@link Annotation annotation}, or <code>null</code>
|
||||
*/
|
||||
static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, String annotationClassName) {
|
||||
return findAnnotation(annotatedElement, resolveAnnotationType(annotatedElement, annotationClassName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the annotation that is annotated on the specified element may be a meta-annotation
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationType the type of annotation
|
||||
* @param <A> the required type of annotation
|
||||
* @return If found, return first matched-type {@link Annotation annotation}, or <code>null</code>
|
||||
*/
|
||||
static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
||||
return (A) filterFirst(getAllDeclaredAnnotations(annotatedElement), a -> isSameType(a, annotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the meta annotations from the the {@link Annotation annotation} type by meta annotation type
|
||||
*
|
||||
* @param annotationType the {@link Annotation annotation} type
|
||||
* @param metaAnnotationType the meta annotation type
|
||||
* @param <A> the type of required annotation
|
||||
* @return if found, return all matched results, or get an {@link Collections#emptyList() empty list}
|
||||
*/
|
||||
static <A extends Annotation> List<A> findMetaAnnotations(Class<? extends Annotation> annotationType,
|
||||
Class<A> metaAnnotationType) {
|
||||
return (List<A>) getAllMetaAnnotations(annotationType, a -> isSameType(a, metaAnnotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the meta annotations from the the the annotated element by meta annotation type
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param metaAnnotationType the meta annotation type
|
||||
* @param <A> the type of required annotation
|
||||
* @return if found, return all matched results, or get an {@link Collections#emptyList() empty list}
|
||||
*/
|
||||
static <A extends Annotation> List<A> findMetaAnnotations(AnnotatedElement annotatedElement,
|
||||
Class<A> metaAnnotationType) {
|
||||
List<A> metaAnnotations = new LinkedList<>();
|
||||
|
||||
for (Annotation annotation : getAllDeclaredAnnotations(annotatedElement)) {
|
||||
metaAnnotations.addAll(findMetaAnnotations(annotation.annotationType(), metaAnnotationType));
|
||||
}
|
||||
|
||||
return unmodifiableList(metaAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the meta annotation from the annotated element by meta annotation type
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param metaAnnotationClassName the class name of meta annotation
|
||||
* @param <A> the type of required annotation
|
||||
* @return {@link #findMetaAnnotation(Class, Class)}
|
||||
*/
|
||||
static <A extends Annotation> A findMetaAnnotation(AnnotatedElement annotatedElement,
|
||||
String metaAnnotationClassName) {
|
||||
return findMetaAnnotation(annotatedElement, resolveAnnotationType(annotatedElement, metaAnnotationClassName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the meta annotation from the annotation type by meta annotation type
|
||||
*
|
||||
* @param annotationType the {@link Annotation annotation} type
|
||||
* @param metaAnnotationType the meta annotation type
|
||||
* @param <A> the type of required annotation
|
||||
* @return If found, return the {@link CollectionUtils#first(Collection)} matched result, return <code>null</code>.
|
||||
* If it requires more result, please consider to use {@link #findMetaAnnotations(Class, Class)}
|
||||
* @see #findMetaAnnotations(Class, Class)
|
||||
*/
|
||||
static <A extends Annotation> A findMetaAnnotation(Class<? extends Annotation> annotationType,
|
||||
Class<A> metaAnnotationType) {
|
||||
return first(findMetaAnnotations(annotationType, metaAnnotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the meta annotation from the annotated element by meta annotation type
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param metaAnnotationType the meta annotation type
|
||||
* @param <A> the type of required annotation
|
||||
* @return If found, return the {@link CollectionUtils#first(Collection)} matched result, return <code>null</code>.
|
||||
* If it requires more result, please consider to use {@link #findMetaAnnotations(AnnotatedElement, Class)}
|
||||
* @see #findMetaAnnotations(AnnotatedElement, Class)
|
||||
*/
|
||||
static <A extends Annotation> A findMetaAnnotation(AnnotatedElement annotatedElement, Class<A> metaAnnotationType) {
|
||||
return first(findMetaAnnotations(annotatedElement, metaAnnotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is annotated the specified annotations or not
|
||||
*
|
||||
* @param type the annotated type
|
||||
* @param matchAll If <code>true</code>, checking all annotation types are present or not, or match any
|
||||
* @param annotationTypes the specified annotation types
|
||||
* @return If the specified annotation types are present, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isAnnotationPresent(Class<?> type,
|
||||
boolean matchAll,
|
||||
Class<? extends Annotation>... annotationTypes) {
|
||||
|
||||
int size = annotationTypes == null ? 0 : annotationTypes.length;
|
||||
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int presentCount = 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Class<? extends Annotation> annotationType = annotationTypes[i];
|
||||
if (findAnnotation(type, annotationType) != null || findMetaAnnotation(type, annotationType) != null) {
|
||||
presentCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return matchAll ? presentCount == size : presentCount > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is annotated the specified annotation or not
|
||||
*
|
||||
* @param type the annotated type
|
||||
* @param annotationType the class of annotation
|
||||
* @return If the specified annotation type is present, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isAnnotationPresent(Class<?> type, Class<? extends Annotation> annotationType) {
|
||||
return isAnnotationPresent(type, true, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is present any specified annotation types
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationClassName the class name of annotation
|
||||
* @return If any specified annotation types are present, return <code>true</code>
|
||||
*/
|
||||
static boolean isAnnotationPresent(AnnotatedElement annotatedElement, String annotationClassName) {
|
||||
ClassLoader classLoader = annotatedElement.getClass().getClassLoader();
|
||||
Class<?> resolvedType = resolveClass(annotationClassName, classLoader);
|
||||
if (!Annotation.class.isAssignableFrom(resolvedType)) {
|
||||
return false;
|
||||
}
|
||||
return isAnnotationPresent(annotatedElement, (Class<? extends Annotation>) resolvedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is present any specified annotation types
|
||||
*
|
||||
* @param annotatedElement the annotated element
|
||||
* @param annotationType the class of annotation
|
||||
* @return If any specified annotation types are present, return <code>true</code>
|
||||
*/
|
||||
static boolean isAnnotationPresent(AnnotatedElement annotatedElement, Class<? extends Annotation> annotationType) {
|
||||
if (isType(annotatedElement)) {
|
||||
return isAnnotationPresent((Class) annotatedElement, annotationType);
|
||||
} else {
|
||||
return annotatedElement.isAnnotationPresent(annotationType) ||
|
||||
findMetaAnnotation(annotatedElement, annotationType) != null; // to find meta-annotation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is annotated all specified annotations or not
|
||||
*
|
||||
* @param type the annotated type
|
||||
* @param annotationTypes the specified annotation types
|
||||
* @return If the specified annotation types are present, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isAllAnnotationPresent(Class<?> type, Class<? extends Annotation>... annotationTypes) {
|
||||
return isAnnotationPresent(type, true, annotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the annotated element is present any specified annotation types
|
||||
*
|
||||
* @param type the annotated type
|
||||
* @param annotationTypes the specified annotation types
|
||||
* @return If any specified annotation types are present, return <code>true</code>
|
||||
*/
|
||||
static boolean isAnyAnnotationPresent(Class<?> type,
|
||||
Class<? extends Annotation>... annotationTypes) {
|
||||
return isAnnotationPresent(type, false, annotationTypes);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* The {@link Comparator} for {@link CharSequence}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class CharSequenceComparator implements Comparator<CharSequence> {
|
||||
|
||||
public final static CharSequenceComparator INSTANCE = new CharSequenceComparator();
|
||||
|
||||
private CharSequenceComparator() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(CharSequence c1, CharSequence c2) {
|
||||
return c1.toString().compareTo(c2.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -18,11 +18,26 @@ package org.apache.dubbo.common.utils;
|
|||
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.apache.dubbo.common.function.Streams.filterAll;
|
||||
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
|
||||
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
|
||||
|
||||
public class ClassUtils {
|
||||
/**
|
||||
|
|
@ -44,6 +59,43 @@ public class ClassUtils {
|
|||
*/
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
|
||||
|
||||
/**
|
||||
* Simple Types including:
|
||||
* <ul>
|
||||
* <li>{@link Void}</li>
|
||||
* <li>{@link Boolean}</li>
|
||||
* <li>{@link Character}</li>
|
||||
* <li>{@link Byte}</li>
|
||||
* <li>{@link Integer}</li>
|
||||
* <li>{@link Float}</li>
|
||||
* <li>{@link Double}</li>
|
||||
* <li>{@link String}</li>
|
||||
* <li>{@link BigDecimal}</li>
|
||||
* <li>{@link BigInteger}</li>
|
||||
* <li>{@link Date}</li>
|
||||
* <li>{@link Object}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see javax.management.openmbean.SimpleType
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static final Set<Class<?>> SIMPLE_TYPES = ofSet(
|
||||
Void.class,
|
||||
Boolean.class,
|
||||
Character.class,
|
||||
Byte.class,
|
||||
Short.class,
|
||||
Integer.class,
|
||||
Long.class,
|
||||
Float.class,
|
||||
Double.class,
|
||||
String.class,
|
||||
BigDecimal.class,
|
||||
BigInteger.class,
|
||||
Date.class,
|
||||
Object.class
|
||||
);
|
||||
|
||||
private static final char PACKAGE_SEPARATOR_CHAR = '.';
|
||||
|
||||
static {
|
||||
|
|
@ -228,18 +280,27 @@ public class ClassUtils {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* The specified type is primitive type or simple type
|
||||
*
|
||||
* @param type the type to test
|
||||
* @return
|
||||
* @deprecated as 2.7.6, use {@link Class#isPrimitive()} plus {@link #isSimpleType(Class)} instead
|
||||
*/
|
||||
public static boolean isPrimitive(Class<?> type) {
|
||||
return type.isPrimitive()
|
||||
|| type == String.class
|
||||
|| type == Character.class
|
||||
|| type == Boolean.class
|
||||
|| type == Byte.class
|
||||
|| type == Short.class
|
||||
|| type == Integer.class
|
||||
|| type == Long.class
|
||||
|| type == Float.class
|
||||
|| type == Double.class
|
||||
|| type == Object.class;
|
||||
return type != null && (type.isPrimitive() || isSimpleType(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* The specified type is simple type or not
|
||||
*
|
||||
* @param type the type to test
|
||||
* @return if <code>type</code> is one element of {@link #SIMPLE_TYPES}, return <code>true</code>, or <code>false</code>
|
||||
* @see #SIMPLE_TYPES
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static boolean isSimpleType(Class<?> type) {
|
||||
return SIMPLE_TYPES.contains(type);
|
||||
}
|
||||
|
||||
public static Object convertPrimitive(Class<?> type, String value) {
|
||||
|
|
@ -285,4 +346,147 @@ public class ClassUtils {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all super classes from the specified type
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param classFilters the filters for classes
|
||||
* @return non-null read-only {@link Set}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static Set<Class<?>> getAllSuperClasses(Class<?> type, Predicate<Class<?>>... classFilters) {
|
||||
|
||||
Set<Class<?>> allSuperClasses = new LinkedHashSet<>();
|
||||
|
||||
Class<?> superClass = type.getSuperclass();
|
||||
|
||||
if (superClass != null) {
|
||||
// add current super class
|
||||
allSuperClasses.add(superClass);
|
||||
// add ancestor classes
|
||||
allSuperClasses.addAll(getAllSuperClasses(superClass));
|
||||
}
|
||||
|
||||
return unmodifiableSet(filterAll(allSuperClasses, classFilters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all interfaces from the specified type
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param interfaceFilters the filters for interfaces
|
||||
* @return non-null read-only {@link Set}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static Set<Class<?>> getAllInterfaces(Class<?> type, Predicate<Class<?>>... interfaceFilters) {
|
||||
|
||||
if (type == null || type.isPrimitive()) {
|
||||
return emptySet();
|
||||
}
|
||||
|
||||
Set<Class<?>> allInterfaces = new LinkedHashSet<>();
|
||||
|
||||
Class<?>[] interfaces = type.getInterfaces();
|
||||
|
||||
if (isNotEmpty(interfaces)) {
|
||||
// add current interfaces
|
||||
allInterfaces.addAll(asList(interfaces));
|
||||
}
|
||||
|
||||
// add all super interfaces
|
||||
getAllSuperClasses(type).forEach(superType -> allInterfaces.addAll(getAllInterfaces(superType)));
|
||||
|
||||
// add all super interfaces from all interfaces
|
||||
allInterfaces.stream()
|
||||
.map(ClassUtils::getAllInterfaces)
|
||||
.flatMap(Collection::stream)
|
||||
.collect(toList())
|
||||
.forEach(allInterfaces::add);
|
||||
|
||||
return filterAll(allInterfaces, interfaceFilters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all inherited types from the specified type
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param typeFilters the filters for types
|
||||
* @return non-null read-only {@link Set}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static Set<Class<?>> getAllInheritedTypes(Class<?> type, Predicate<Class<?>>... typeFilters) {
|
||||
// Add all super classes
|
||||
Set<Class<?>> types = new LinkedHashSet<>(getAllSuperClasses(type, typeFilters));
|
||||
// Add all interface classes
|
||||
types.addAll(getAllInterfaces(type, typeFilters));
|
||||
return unmodifiableSet(types);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* the semantics is same as {@link Class#isAssignableFrom(Class)}
|
||||
*
|
||||
* @param superType the super type
|
||||
* @param targetType the target type
|
||||
* @return see {@link Class#isAssignableFrom(Class)}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static boolean isAssignableFrom(Class<?> superType, Class<?> targetType) {
|
||||
// any argument is null
|
||||
if (superType == null || targetType == null) {
|
||||
return false;
|
||||
}
|
||||
// equals
|
||||
if (Objects.equals(superType, targetType)) {
|
||||
return true;
|
||||
}
|
||||
// isAssignableFrom
|
||||
return superType.isAssignableFrom(targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the specified class name is present in the {@link ClassLoader}
|
||||
*
|
||||
* @param className the name of {@link Class}
|
||||
* @param classLoader {@link ClassLoader}
|
||||
* @return If found, return <code>true</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static boolean isPresent(String className, ClassLoader classLoader) {
|
||||
try {
|
||||
forName(className, classLoader);
|
||||
} catch (Throwable ignored) { // Ignored
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the {@link Class} by the specified name and {@link ClassLoader}
|
||||
*
|
||||
* @param className the name of {@link Class}
|
||||
* @param classLoader {@link ClassLoader}
|
||||
* @return If can't be resolved , return <code>null</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static Class<?> resolveClass(String className, ClassLoader classLoader) {
|
||||
Class<?> targetClass = null;
|
||||
try {
|
||||
targetClass = forName(className, classLoader);
|
||||
} catch (Throwable ignored) { // Ignored
|
||||
}
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is generic class or not?
|
||||
*
|
||||
* @param type the target type
|
||||
* @return if the target type is not null or <code>void</code> or Void.class, return <code>true</code>, or false
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static boolean isGenericClass(Class<?> type) {
|
||||
return type != null && !void.class.equals(type) && !Void.class.equals(type);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
@ -26,7 +27,6 @@ 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;
|
||||
|
||||
|
|
@ -270,9 +270,112 @@ public class CollectionUtils {
|
|||
* @return read-only {@link Set}
|
||||
*/
|
||||
public static <T> Set<T> ofSet(T... values) {
|
||||
if (values == null || values.length < 1) {
|
||||
int size = values == null ? 0 : values.length;
|
||||
if (size < 1) {
|
||||
return emptySet();
|
||||
}
|
||||
return unmodifiableSet(new LinkedHashSet<>(asList(values)));
|
||||
|
||||
float loadFactor = 1f / ((size + 1) * 1.0f);
|
||||
|
||||
if (loadFactor > 0.75f) {
|
||||
loadFactor = 0.75f;
|
||||
}
|
||||
|
||||
Set<T> elements = new LinkedHashSet<>(size, loadFactor);
|
||||
for (int i = 0; i < size; i++) {
|
||||
elements.add(values[i]);
|
||||
}
|
||||
return unmodifiableSet(elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the specified {@link Collection}
|
||||
*
|
||||
* @param collection the specified {@link Collection}
|
||||
* @return must be positive number
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static int size(Collection<?> collection) {
|
||||
return collection == null ? 0 : collection.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified collection with another, the main implementation references
|
||||
* {@link AbstractSet}
|
||||
*
|
||||
* @param one {@link Collection}
|
||||
* @param another {@link Collection}
|
||||
* @return if equals, return <code>true</code>, or <code>false</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static boolean equals(Collection<?> one, Collection<?> another) {
|
||||
|
||||
if (one == another) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isEmpty(one) && isEmpty(another)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size(one) != size(another)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return one.containsAll(another);
|
||||
} catch (ClassCastException unused) {
|
||||
return false;
|
||||
} catch (NullPointerException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the multiple values into {@link Collection the specified collection}
|
||||
*
|
||||
* @param collection {@link Collection the specified collection}
|
||||
* @param values the multiple values
|
||||
* @param <T> the type of values
|
||||
* @return the effected count after added
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static <T> int addAll(Collection<T> collection, T... values) {
|
||||
|
||||
int size = values == null ? 0 : values.length;
|
||||
|
||||
if (collection == null || size < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int effectedCount = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (collection.add(values[i])) {
|
||||
effectedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return effectedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the first element from the specified collection
|
||||
*
|
||||
* @param values the collection object
|
||||
* @param <T> the type of element of collection
|
||||
* @return if found, return the first one, or <code>null</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static <T> T first(Collection<T> values) {
|
||||
if (isEmpty(values)) {
|
||||
return null;
|
||||
}
|
||||
if (values instanceof List) {
|
||||
List<T> list = (List<T>) values;
|
||||
return list.get(0);
|
||||
} else {
|
||||
return values.iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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.common.utils;
|
||||
|
||||
|
||||
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.6
|
||||
*/
|
||||
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);
|
||||
// }
|
||||
}
|
||||
|
|
@ -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.common.utils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Java Reflection {@link Member} Utilities class
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface MemberUtils {
|
||||
|
||||
/**
|
||||
* check the specified {@link Member member} is static or not ?
|
||||
*
|
||||
* @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
|
||||
* @return Iff <code>member</code> is static one, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isStatic(Member member) {
|
||||
return member != null && Modifier.isStatic(member.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* check the specified {@link Member member} is private or not ?
|
||||
*
|
||||
* @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
|
||||
* @return Iff <code>member</code> is private one, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isPrivate(Member member) {
|
||||
return member != null && Modifier.isPrivate(member.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* check the specified {@link Member member} is public or not ?
|
||||
*
|
||||
* @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
|
||||
* @return Iff <code>member</code> is public one, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
static boolean isPublic(Member member) {
|
||||
return member != null && Modifier.isPublic(member.getModifiers());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* The Comparator class for {@link Method}, the comparison rule :
|
||||
* <ol>
|
||||
* <li>Comparing to two {@link Method#getName() method names} {@link String#compareTo(String) lexicographically}.
|
||||
* If equals, go to step 2</li>
|
||||
* <li>Comparing to the count of two method parameters. If equals, go to step 3</li>
|
||||
* <li>Comparing to the type names of methods parameter {@link String#compareTo(String) lexicographically}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class MethodComparator implements Comparator<Method> {
|
||||
|
||||
public final static MethodComparator INSTANCE = new MethodComparator();
|
||||
|
||||
private MethodComparator() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Method m1, Method m2) {
|
||||
|
||||
if (m1.equals(m2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Step 1
|
||||
String n1 = m1.getName();
|
||||
String n2 = m2.getName();
|
||||
int value = n1.compareTo(n2);
|
||||
|
||||
if (value == 0) { // Step 2
|
||||
|
||||
Class[] types1 = m1.getParameterTypes();
|
||||
Class[] types2 = m2.getParameterTypes();
|
||||
|
||||
value = types1.length - types2.length;
|
||||
|
||||
if (value == 0) { // Step 3
|
||||
for (int i = 0; i < types1.length; i++) {
|
||||
value = types1[i].getName().compareTo(types2[i].getName());
|
||||
if (value != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Integer.compare(value, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,17 +16,32 @@
|
|||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.apache.dubbo.common.function.Streams.filterAll;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllInheritedTypes;
|
||||
import static org.apache.dubbo.common.utils.MemberUtils.isPrivate;
|
||||
import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
|
||||
import static org.apache.dubbo.common.utils.ReflectUtils.EMPTY_CLASS_ARRAY;
|
||||
import static org.apache.dubbo.common.utils.ReflectUtils.resolveTypes;
|
||||
|
||||
/**
|
||||
* Miscellaneous method utility methods.
|
||||
* Mainly for internal use within the framework.
|
||||
*
|
||||
* @author LiZhenNet
|
||||
* @since 2.7.2
|
||||
*/
|
||||
public class MethodUtils {
|
||||
public interface MethodUtils {
|
||||
|
||||
/**
|
||||
* Return {@code true} if the provided method is a set method.
|
||||
|
|
@ -101,4 +116,277 @@ public class MethodUtils {
|
|||
public static boolean isDeprecated(Method method) {
|
||||
return method.getAnnotation(Deprecated.class) != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Predicate} for {@link Method} to exclude the specified declared class
|
||||
*
|
||||
* @param declaredClass the declared class to exclude
|
||||
* @return non-null
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static Predicate<Method> excludedDeclaredClass(Class<?> declaredClass) {
|
||||
return method -> !Objects.equals(declaredClass, method.getDeclaringClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all {@link Method methods} of the declared class
|
||||
*
|
||||
* @param declaringClass the declared class
|
||||
* @param includeInheritedTypes include the inherited types, e,g. super classes or interfaces
|
||||
* @param publicOnly only public method
|
||||
* @param methodsToFilter (optional) the methods to be filtered
|
||||
* @return non-null read-only {@link List}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static List<Method> getMethods(Class<?> declaringClass, boolean includeInheritedTypes, boolean publicOnly,
|
||||
Predicate<Method>... methodsToFilter) {
|
||||
|
||||
if (declaringClass == null || declaringClass.isPrimitive()) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
// All declared classes
|
||||
List<Class<?>> declaredClasses = new LinkedList<>();
|
||||
// Add the top declaring class
|
||||
declaredClasses.add(declaringClass);
|
||||
// If the super classes are resolved, all them into declaredClasses
|
||||
if (includeInheritedTypes) {
|
||||
declaredClasses.addAll(getAllInheritedTypes(declaringClass));
|
||||
}
|
||||
|
||||
// All methods
|
||||
List<Method> allMethods = new LinkedList<>();
|
||||
|
||||
for (Class<?> classToSearch : declaredClasses) {
|
||||
Method[] methods = publicOnly ? classToSearch.getMethods() : classToSearch.getDeclaredMethods();
|
||||
// Add the declared methods or public methods
|
||||
for (Method method : methods) {
|
||||
allMethods.add(method);
|
||||
}
|
||||
}
|
||||
|
||||
return unmodifiableList(filterAll(allMethods, methodsToFilter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all declared {@link Method methods} of the declared class, excluding the inherited methods
|
||||
*
|
||||
* @param declaringClass the declared class
|
||||
* @param methodsToFilter (optional) the methods to be filtered
|
||||
* @return non-null read-only {@link List}
|
||||
* @see #getMethods(Class, boolean, boolean, Predicate[])
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static List<Method> getDeclaredMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
|
||||
return getMethods(declaringClass, false, false, methodsToFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all public {@link Method methods} of the declared class, including the inherited methods.
|
||||
*
|
||||
* @param declaringClass the declared class
|
||||
* @param methodsToFilter (optional) the methods to be filtered
|
||||
* @return non-null read-only {@link List}
|
||||
* @see #getMethods(Class, boolean, boolean, Predicate[])
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static List<Method> getMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
|
||||
return getMethods(declaringClass, false, true, methodsToFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all declared {@link Method methods} of the declared class, including the inherited methods.
|
||||
*
|
||||
* @param declaringClass the declared class
|
||||
* @param methodsToFilter (optional) the methods to be filtered
|
||||
* @return non-null read-only {@link List}
|
||||
* @see #getMethods(Class, boolean, boolean, Predicate[])
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static List<Method> getAllDeclaredMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
|
||||
return getMethods(declaringClass, true, false, methodsToFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all public {@link Method methods} of the declared class, including the inherited methods.
|
||||
*
|
||||
* @param declaringClass the declared class
|
||||
* @param methodsToFilter (optional) the methods to be filtered
|
||||
* @return non-null read-only {@link List}
|
||||
* @see #getMethods(Class, boolean, boolean, Predicate[])
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static List<Method> getAllMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
|
||||
return getMethods(declaringClass, true, true, methodsToFilter);
|
||||
}
|
||||
|
||||
// static List<Method> getOverriderMethods(Class<?> implementationClass, Class<?>... superTypes) {
|
||||
|
||||
//
|
||||
|
||||
// }
|
||||
|
||||
/**
|
||||
* Find the {@link Method} by the the specified type and method name without the parameter types
|
||||
*
|
||||
* @param type the target type
|
||||
* @param methodName the specified method name
|
||||
* @return if not found, return <code>null</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static Method findMethod(Class type, String methodName) {
|
||||
return findMethod(type, methodName, EMPTY_CLASS_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@link Method} by the the specified type, method name and parameter types
|
||||
*
|
||||
* @param type the target type
|
||||
* @param methodName the method name
|
||||
* @param parameterTypes the parameter types
|
||||
* @return if not found, return <code>null</code>
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static Method findMethod(Class type, String methodName, Class<?>... parameterTypes) {
|
||||
Method method = null;
|
||||
try {
|
||||
method = type.getDeclaredMethod(methodName, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the target object and method
|
||||
*
|
||||
* @param object the target object
|
||||
* @param methodName the method name
|
||||
* @param methodParameters the method parameters
|
||||
* @param <T> the return type
|
||||
* @return the target method's execution result
|
||||
* @since 2.7.6
|
||||
*/
|
||||
static <T> T invokeMethod(Object object, String methodName, Object... methodParameters) {
|
||||
Class type = object.getClass();
|
||||
Class[] parameterTypes = resolveTypes(methodParameters);
|
||||
Method method = findMethod(type, methodName, parameterTypes);
|
||||
T value = null;
|
||||
|
||||
try {
|
||||
final boolean isAccessible = method.isAccessible();
|
||||
|
||||
if (!isAccessible) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
value = (T) method.invoke(object, methodParameters);
|
||||
method.setAccessible(isAccessible);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether one method, as a member of a given type,
|
||||
* overrides another method.
|
||||
*
|
||||
* @param overrider the first method, possible overrider
|
||||
* @param overridden the second method, possibly being overridden
|
||||
* @return {@code true} if and only if the first method overrides
|
||||
* the second
|
||||
* @jls 8.4.8 Inheritance, Overriding, and Hiding
|
||||
* @jls 9.4.1 Inheritance and Overriding
|
||||
* @see Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)
|
||||
*/
|
||||
static boolean overrides(Method overrider, Method overridden) {
|
||||
|
||||
if (overrider == null || overridden == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// equality comparison: If two methods are same
|
||||
if (Objects.equals(overrider, overridden)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Modifiers comparison: Any method must be non-static method
|
||||
if (isStatic(overrider) || isStatic(overridden)) { //
|
||||
return false;
|
||||
}
|
||||
|
||||
// Modifiers comparison: the accessibility of any method must not be private
|
||||
if (isPrivate(overrider) || isPrivate(overridden)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inheritance comparison: The declaring class of overrider must be inherit from the overridden's
|
||||
if (!overridden.getDeclaringClass().isAssignableFrom(overrider.getDeclaringClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method comparison: must not be "default" method
|
||||
if (overrider.isDefault()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method comparison: The method name must be equal
|
||||
if (!Objects.equals(overrider.getName(), overridden.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method comparison: The count of method parameters must be equal
|
||||
if (!Objects.equals(overrider.getParameterCount(), overridden.getParameterCount())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method comparison: Any parameter type of overrider must equal the overridden's
|
||||
for (int i = 0; i < overrider.getParameterCount(); i++) {
|
||||
if (!Objects.equals(overridden.getParameterTypes()[i], overrider.getParameterTypes()[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method comparison: The return type of overrider must be inherit from the overridden's
|
||||
if (!overridden.getReturnType().isAssignableFrom(overrider.getReturnType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Throwable comparison: "throws" Throwable list will be ignored, trust the compiler verify
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the nearest overridden {@link Method method} from the inherited class
|
||||
*
|
||||
* @param overrider the overrider {@link Method method}
|
||||
* @return if found, the overrider <code>method</code>, or <code>null</code>
|
||||
*/
|
||||
static Method findNearestOverriddenMethod(Method overrider) {
|
||||
Class<?> declaringClass = overrider.getDeclaringClass();
|
||||
Method overriddenMethod = null;
|
||||
for (Class<?> inheritedType : getAllInheritedTypes(declaringClass)) {
|
||||
overriddenMethod = findOverriddenMethod(overrider, inheritedType);
|
||||
if (overriddenMethod != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return overriddenMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the overridden {@link Method method} from the declaring class
|
||||
*
|
||||
* @param overrider the overrider {@link Method method}
|
||||
* @param declaringClass the class that is declaring the overridden {@link Method method}
|
||||
* @return if found, the overrider <code>method</code>, or <code>null</code>
|
||||
*/
|
||||
static Method findOverriddenMethod(Method overrider, Class<?> declaringClass) {
|
||||
List<Method> matchedMethods = getAllMethods(declaringClass, method -> overrides(overrider, method));
|
||||
return matchedMethods.isEmpty() ? null : matchedMethods.get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import java.util.stream.Stream;
|
|||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* ReflectUtils
|
||||
|
|
@ -1259,6 +1260,15 @@ public final class ReflectUtils {
|
|||
return unmodifiableSet(hierarchicalTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value from the specified bean and its property.
|
||||
*
|
||||
* @param bean the bean instance
|
||||
* @param propertyName the name of property
|
||||
* @param <T> the type of property value
|
||||
* @return
|
||||
* @since 2.7.5
|
||||
*/
|
||||
public static <T> T getProperty(Object bean, String propertyName) {
|
||||
Class<?> beanClass = bean.getClass();
|
||||
BeanInfo beanInfo = null;
|
||||
|
|
@ -1282,4 +1292,28 @@ public final class ReflectUtils {
|
|||
return propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the types of the specified values
|
||||
*
|
||||
* @param values the values
|
||||
* @return If can't be resolved, return {@link ReflectUtils#EMPTY_CLASS_ARRAY empty class array}
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public static Class[] resolveTypes(Object... values) {
|
||||
|
||||
if (isEmpty(values)) {
|
||||
return EMPTY_CLASS_ARRAY;
|
||||
}
|
||||
|
||||
int size = values.length;
|
||||
|
||||
Class[] types = new Class[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Object value = values[i];
|
||||
types[i] = value == null ? null : value.getClass();
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import org.apache.dubbo.config.annotation.Service;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
|
||||
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.isGenericClass;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* The resolver class for {@link Service @Service}
|
||||
*
|
||||
* @see Service
|
||||
* @see com.alibaba.dubbo.config.annotation.Service
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class ServiceAnnotationResolver {
|
||||
|
||||
private final Annotation serviceAnnotation;
|
||||
|
||||
private final Class<?> serviceType;
|
||||
|
||||
public ServiceAnnotationResolver(Class<?> serviceType) throws IllegalArgumentException {
|
||||
this.serviceType = serviceType;
|
||||
this.serviceAnnotation = getServiceAnnotation(serviceType);
|
||||
}
|
||||
|
||||
private Annotation getServiceAnnotation(Class<?> serviceType) {
|
||||
|
||||
Annotation serviceAnnotation = serviceType.getAnnotation(Service.class);
|
||||
|
||||
if (serviceAnnotation == null) {
|
||||
serviceAnnotation = serviceType.getAnnotation(com.alibaba.dubbo.config.annotation.Service.class);
|
||||
}
|
||||
|
||||
if (serviceAnnotation == null) {
|
||||
throw new IllegalArgumentException(format("@%s or @%s can't be found in the service type[%s].",
|
||||
Service.class.getName(),
|
||||
com.alibaba.dubbo.config.annotation.Service.class.getName(),
|
||||
serviceType.getName()
|
||||
));
|
||||
}
|
||||
|
||||
return serviceAnnotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the class name of interface
|
||||
*
|
||||
* @return if not found, return <code>null</code>
|
||||
*/
|
||||
public String resolveInterfaceClassName() {
|
||||
|
||||
Class interfaceClass = null;
|
||||
// first, try to get the value from "interfaceName" attribute
|
||||
String interfaceName = resolveAttribute("interfaceName");
|
||||
|
||||
if (isEmpty(interfaceName)) { // If not found, try "interfaceClass"
|
||||
interfaceClass = resolveAttribute("interfaceClass");
|
||||
} else {
|
||||
interfaceClass = resolveClass(interfaceName, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
if (isGenericClass(interfaceClass)) {
|
||||
interfaceName = interfaceClass.getName();
|
||||
} else {
|
||||
interfaceName = null;
|
||||
}
|
||||
|
||||
if (isEmpty(interfaceName)) { // If not fund, try to get the first interface from the service type
|
||||
Class[] interfaces = serviceType.getInterfaces();
|
||||
if (isNotEmpty(interfaces)) {
|
||||
interfaceName = interfaces[0].getName();
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceName;
|
||||
}
|
||||
|
||||
public String resolveVersion() {
|
||||
return resolveAttribute("version");
|
||||
}
|
||||
|
||||
public String resolveGroup() {
|
||||
return resolveAttribute("group");
|
||||
}
|
||||
|
||||
private <T> T resolveAttribute(String attributeName) {
|
||||
return getAttribute(serviceAnnotation, attributeName);
|
||||
}
|
||||
|
||||
public Annotation getServiceAnnotation() {
|
||||
return serviceAnnotation;
|
||||
}
|
||||
|
||||
public Class<?> getServiceType() {
|
||||
return serviceType;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static java.util.stream.StreamSupport.stream;
|
||||
import static org.apache.dubbo.common.function.Predicates.and;
|
||||
import static org.apache.dubbo.common.function.Streams.filterAll;
|
||||
import static org.apache.dubbo.common.function.Streams.filterList;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllSuperClasses;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
|
||||
|
||||
/**
|
||||
* The utilities class for {@link Type}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface TypeUtils {
|
||||
|
||||
Predicate<Class<?>> NON_OBJECT_TYPE_FILTER = t -> !Objects.equals(Object.class, t);
|
||||
|
||||
static boolean isParameterizedType(Type type) {
|
||||
return type instanceof ParameterizedType;
|
||||
}
|
||||
|
||||
static Type getRawType(Type type) {
|
||||
if (isParameterizedType(type)) {
|
||||
return ((ParameterizedType) type).getRawType();
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
static Class<?> getRawClass(Type type) {
|
||||
Type rawType = getRawType(type);
|
||||
if (isClass(rawType)) {
|
||||
return (Class) rawType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean isClass(Type type) {
|
||||
return type instanceof Class;
|
||||
}
|
||||
|
||||
static <T> Class<T> findActualTypeArgument(Type type, Class<?> interfaceClass, int index) {
|
||||
return (Class<T>) findActualTypeArguments(type, interfaceClass).get(index);
|
||||
}
|
||||
|
||||
static List<Class<?>> findActualTypeArguments(Type type, Class<?> interfaceClass) {
|
||||
|
||||
List<Class<?>> actualTypeArguments = new LinkedList<>();
|
||||
|
||||
getAllGenericTypes(type, t -> isAssignableFrom(interfaceClass, getRawClass(t)))
|
||||
.forEach(parameterizedType -> {
|
||||
Class<?> rawClass = getRawClass(parameterizedType);
|
||||
Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
Type typeArgument = typeArguments[i];
|
||||
if (typeArgument instanceof Class) {
|
||||
actualTypeArguments.add(i, (Class) typeArgument);
|
||||
}
|
||||
}
|
||||
Class<?> superClass = rawClass.getSuperclass();
|
||||
if (superClass != null) {
|
||||
actualTypeArguments.addAll(findActualTypeArguments(superClass, interfaceClass));
|
||||
}
|
||||
});
|
||||
|
||||
return unmodifiableList(actualTypeArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified types' generic types(including super classes and interfaces) that are assignable from {@link ParameterizedType} interface
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<ParameterizedType> getGenericTypes(Type type, Predicate<ParameterizedType>... typeFilters) {
|
||||
|
||||
Class<?> rawClass = getRawClass(type);
|
||||
|
||||
if (rawClass == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<Type> genericTypes = new LinkedList<>();
|
||||
|
||||
genericTypes.add(rawClass.getGenericSuperclass());
|
||||
genericTypes.addAll(asList(rawClass.getGenericInterfaces()));
|
||||
|
||||
return unmodifiableList(
|
||||
filterList(genericTypes, TypeUtils::isParameterizedType)
|
||||
.stream()
|
||||
.map(ParameterizedType.class::cast)
|
||||
.filter(and(typeFilters))
|
||||
.collect(toList())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all generic types(including super classes and interfaces) that are assignable from {@link ParameterizedType} interface
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<ParameterizedType> getAllGenericTypes(Type type, Predicate<ParameterizedType>... typeFilters) {
|
||||
List<ParameterizedType> allGenericTypes = new LinkedList<>();
|
||||
// Add generic super classes
|
||||
allGenericTypes.addAll(getAllGenericSuperClasses(type, typeFilters));
|
||||
// Add generic super interfaces
|
||||
allGenericTypes.addAll(getAllGenericInterfaces(type, typeFilters));
|
||||
// wrap unmodifiable object
|
||||
return unmodifiableList(allGenericTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all generic super classes that are assignable from {@link ParameterizedType} interface
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<ParameterizedType> getAllGenericSuperClasses(Type type, Predicate<ParameterizedType>... typeFilters) {
|
||||
|
||||
Class<?> rawClass = getRawClass(type);
|
||||
|
||||
if (rawClass == null || rawClass.isInterface()) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<Class<?>> allTypes = new LinkedList<>();
|
||||
// Add current class
|
||||
allTypes.add(rawClass);
|
||||
// Add all super classes
|
||||
allTypes.addAll(getAllSuperClasses(rawClass, NON_OBJECT_TYPE_FILTER));
|
||||
|
||||
List<ParameterizedType> allGenericSuperClasses = allTypes
|
||||
.stream()
|
||||
.map(Class::getGenericSuperclass)
|
||||
.filter(TypeUtils::isParameterizedType)
|
||||
.map(ParameterizedType.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return unmodifiableList(filterAll(allGenericSuperClasses, typeFilters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all generic interfaces that are assignable from {@link ParameterizedType} interface
|
||||
*
|
||||
* @param type the specified type
|
||||
* @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
|
||||
* @return non-null read-only {@link List}
|
||||
*/
|
||||
static List<ParameterizedType> getAllGenericInterfaces(Type type, Predicate<ParameterizedType>... typeFilters) {
|
||||
|
||||
Class<?> rawClass = getRawClass(type);
|
||||
|
||||
if (rawClass == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<Class<?>> allTypes = new LinkedList<>();
|
||||
// Add current class
|
||||
allTypes.add(rawClass);
|
||||
// Add all super classes
|
||||
allTypes.addAll(getAllSuperClasses(rawClass, NON_OBJECT_TYPE_FILTER));
|
||||
// Add all super interfaces
|
||||
allTypes.addAll(getAllInterfaces(rawClass));
|
||||
|
||||
List<ParameterizedType> allGenericInterfaces = allTypes
|
||||
.stream()
|
||||
.map(Class::getGenericInterfaces)
|
||||
.map(Arrays::asList)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(TypeUtils::isParameterizedType)
|
||||
.map(ParameterizedType.class::cast)
|
||||
.collect(toList());
|
||||
|
||||
return unmodifiableList(filterAll(allGenericInterfaces, typeFilters));
|
||||
}
|
||||
|
||||
static String getClassName(Type type) {
|
||||
return getRawType(type).getTypeName();
|
||||
}
|
||||
|
||||
static Set<String> getClassNames(Iterable<? extends Type> types) {
|
||||
return stream(types.spliterator(), false)
|
||||
.map(TypeUtils::getClassName)
|
||||
.collect(toSet());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# org.apache.dubbo.common.convert.Converter
|
||||
string-to-boolean=org.apache.dubbo.common.convert.StringToBooleanConverter
|
||||
string-to-character=org.apache.dubbo.common.convert.StringToCharacterConverter
|
||||
string-to-char-array=org.apache.dubbo.common.convert.StringToCharArrayConverter
|
||||
string-to-double=org.apache.dubbo.common.convert.StringToDoubleConverter
|
||||
string-to-float=org.apache.dubbo.common.convert.StringToFloatConverter
|
||||
string-to-integer=org.apache.dubbo.common.convert.StringToIntegerConverter
|
||||
string-to-long=org.apache.dubbo.common.convert.StringToLongConverter
|
||||
string-to-optional=org.apache.dubbo.common.convert.StringToOptionalConverter
|
||||
string-to-short=org.apache.dubbo.common.convert.StringToShortConverter
|
||||
string-to-string=org.apache.dubbo.common.convert.StringToStringConverter
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# org.apache.dubbo.common.convert.multiple.MultiValueConverter
|
||||
string-to-array=org.apache.dubbo.common.convert.multiple.StringToArrayConverter
|
||||
string-to-blocking-deque=org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter
|
||||
string-to-blocking-queue=org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter
|
||||
string-to-collection=org.apache.dubbo.common.convert.multiple.StringToCollectionConverter
|
||||
string-to-deque=org.apache.dubbo.common.convert.multiple.StringToDequeConverter
|
||||
string-to-list=org.apache.dubbo.common.convert.multiple.StringToListConverter
|
||||
string-to-navigable-set=org.apache.dubbo.common.convert.multiple.StringToNavigableSetConverter
|
||||
string-to-queue=org.apache.dubbo.common.convert.multiple.StringToQueueConverter
|
||||
string-to-set=org.apache.dubbo.common.convert.multiple.StringToSetConverter
|
||||
string-to-sorted-set=org.apache.dubbo.common.convert.multiple.StringToSortedSetConverter
|
||||
string-to-transfer-queue=org.apache.dubbo.common.convert.multiple.StringToTransferQueueConverter
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.common.utils;
|
||||
|
||||
import org.apache.dubbo.common.extension.Adaptive;
|
||||
import org.apache.dubbo.config.annotation.Service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.excludedType;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findMetaAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findMetaAnnotations;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAllDeclaredAnnotations;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAllMetaAnnotations;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getDeclaredAnnotations;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getMetaAnnotations;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getValue;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnyAnnotationPresent;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isSameType;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isType;
|
||||
import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link AnnotationUtils} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class AnnotationUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testIsType() throws NoSuchMethodException {
|
||||
// null checking
|
||||
assertFalse(isType(null));
|
||||
// Method checking
|
||||
assertFalse(isType(findMethod(A.class, "execute")));
|
||||
// Class checking
|
||||
assertTrue(isType(A.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSameType() {
|
||||
assertTrue(isSameType(A.class.getAnnotation(Service.class), Service.class));
|
||||
assertFalse(isSameType(A.class.getAnnotation(Service.class), Deprecated.class));
|
||||
assertFalse(isSameType(A.class.getAnnotation(Service.class), null));
|
||||
assertFalse(isSameType(null, Deprecated.class));
|
||||
assertFalse(isSameType(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludedType() {
|
||||
assertFalse(excludedType(Service.class).test(A.class.getAnnotation(Service.class)));
|
||||
assertTrue(excludedType(Service.class).test(A.class.getAnnotation(Deprecated.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAttribute() {
|
||||
Annotation annotation = A.class.getAnnotation(Service.class);
|
||||
assertEquals("java.lang.CharSequence", getAttribute(annotation, "interfaceName"));
|
||||
assertEquals(CharSequence.class, getAttribute(annotation, "interfaceClass"));
|
||||
assertEquals("", getAttribute(annotation, "version"));
|
||||
assertEquals("", getAttribute(annotation, "group"));
|
||||
assertEquals("", getAttribute(annotation, "path"));
|
||||
assertEquals(true, getAttribute(annotation, "export"));
|
||||
assertEquals(false, getAttribute(annotation, "deprecated"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetValue() {
|
||||
Adaptive adaptive = A.class.getAnnotation(Adaptive.class);
|
||||
String[] value = getValue(adaptive);
|
||||
assertEquals(asList("a", "b", "c"), asList(value));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotations() {
|
||||
List<Annotation> annotations = getDeclaredAnnotations(A.class);
|
||||
assertADeclaredAnnotations(annotations, 0);
|
||||
|
||||
annotations = getDeclaredAnnotations(A.class, a -> isSameType(a, Service.class));
|
||||
assertEquals(1, annotations.size());
|
||||
Service service = (Service) annotations.get(0);
|
||||
assertEquals("java.lang.CharSequence", service.interfaceName());
|
||||
assertEquals(CharSequence.class, service.interfaceClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllDeclaredAnnotations() {
|
||||
List<Annotation> annotations = getAllDeclaredAnnotations(A.class);
|
||||
assertADeclaredAnnotations(annotations, 0);
|
||||
|
||||
annotations = getAllDeclaredAnnotations(B.class);
|
||||
assertTrue(isSameType(annotations.get(0), Service5.class));
|
||||
assertADeclaredAnnotations(annotations, 1);
|
||||
|
||||
annotations = new LinkedList<>(getAllDeclaredAnnotations(C.class));
|
||||
assertTrue(isSameType(annotations.get(0), MyAdaptive.class));
|
||||
assertTrue(isSameType(annotations.get(1), Service5.class));
|
||||
assertADeclaredAnnotations(annotations, 2);
|
||||
|
||||
annotations = getAllDeclaredAnnotations(findMethod(A.class, "execute"));
|
||||
MyAdaptive myAdaptive = (MyAdaptive) annotations.get(0);
|
||||
assertArrayEquals(new String[]{"e"}, myAdaptive.value());
|
||||
|
||||
annotations = getAllDeclaredAnnotations(findMethod(B.class, "execute"));
|
||||
Adaptive adaptive = (Adaptive) annotations.get(0);
|
||||
assertArrayEquals(new String[]{"f"}, adaptive.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMetaAnnotations() {
|
||||
List<Annotation> metaAnnotations = getMetaAnnotations(Service.class, a -> isSameType(a, Inherited.class));
|
||||
assertEquals(1, metaAnnotations.size());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(0).annotationType());
|
||||
|
||||
metaAnnotations = getMetaAnnotations(Service.class);
|
||||
assertEquals(1, metaAnnotations.size());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(0).annotationType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllMetaAnnotations() {
|
||||
List<Annotation> metaAnnotations = getAllMetaAnnotations(Service5.class);
|
||||
int offset = 0;
|
||||
assertEquals(9, metaAnnotations.size());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Service4.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Service3.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Service2.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Service.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
|
||||
metaAnnotations = getAllMetaAnnotations(MyAdaptive.class);
|
||||
offset = 0;
|
||||
assertEquals(2, metaAnnotations.size());
|
||||
assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
|
||||
assertEquals(Adaptive.class, metaAnnotations.get(offset++).annotationType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsAnnotationPresent() {
|
||||
assertTrue(isAnnotationPresent(A.class, true, Service.class));
|
||||
assertTrue(isAnnotationPresent(A.class, true, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
|
||||
assertTrue(isAnnotationPresent(A.class, Service.class));
|
||||
assertTrue(isAnnotationPresent(A.class, "org.apache.dubbo.config.annotation.Service"));
|
||||
assertTrue(AnnotationUtils.isAllAnnotationPresent(A.class, Service.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
|
||||
assertTrue(isAnnotationPresent(A.class, Deprecated.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAnyAnnotationPresent() {
|
||||
assertTrue(isAnyAnnotationPresent(A.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class, Deprecated.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, Service.class, Deprecated.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, com.alibaba.dubbo.config.annotation.Service.class, Deprecated.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, Service.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, com.alibaba.dubbo.config.annotation.Service.class));
|
||||
assertTrue(isAnyAnnotationPresent(A.class, Deprecated.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotation() {
|
||||
assertNotNull(getAnnotation(A.class, "org.apache.dubbo.config.annotation.Service"));
|
||||
assertNotNull(getAnnotation(A.class, "com.alibaba.dubbo.config.annotation.Service"));
|
||||
assertNotNull(getAnnotation(A.class, "org.apache.dubbo.common.extension.Adaptive"));
|
||||
assertNull(getAnnotation(A.class, "java.lang.Deprecated"));
|
||||
assertNull(getAnnotation(A.class, "java.lang.String"));
|
||||
assertNull(getAnnotation(A.class, "NotExistedClass"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAnnotation() {
|
||||
Service service = findAnnotation(A.class, Service.class);
|
||||
assertEquals("java.lang.CharSequence", service.interfaceName());
|
||||
assertEquals(CharSequence.class, service.interfaceClass());
|
||||
|
||||
service = findAnnotation(B.class, Service.class);
|
||||
assertEquals(CharSequence.class, service.interfaceClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMetaAnnotations() {
|
||||
List<Service> services = findMetaAnnotations(B.class, Service.class);
|
||||
assertEquals(1, services.size());
|
||||
|
||||
Service service = services.get(0);
|
||||
assertEquals("", service.interfaceName());
|
||||
assertEquals(Cloneable.class, service.interfaceClass());
|
||||
|
||||
services = findMetaAnnotations(Service5.class, Service.class);
|
||||
assertEquals(1, services.size());
|
||||
|
||||
service = services.get(0);
|
||||
assertEquals("", service.interfaceName());
|
||||
assertEquals(Cloneable.class, service.interfaceClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMetaAnnotation() {
|
||||
Service service = findMetaAnnotation(B.class, Service.class);
|
||||
assertEquals(Cloneable.class, service.interfaceClass());
|
||||
|
||||
service = findMetaAnnotation(B.class, "org.apache.dubbo.config.annotation.Service");
|
||||
assertEquals(Cloneable.class, service.interfaceClass());
|
||||
|
||||
service = findMetaAnnotation(Service5.class, Service.class);
|
||||
assertEquals(Cloneable.class, service.interfaceClass());
|
||||
}
|
||||
|
||||
@Service(interfaceName = "java.lang.CharSequence", interfaceClass = CharSequence.class)
|
||||
@com.alibaba.dubbo.config.annotation.Service(interfaceName = "java.lang.CharSequence", interfaceClass = CharSequence.class)
|
||||
@Adaptive(value = {"a", "b", "c"})
|
||||
static class A {
|
||||
|
||||
@MyAdaptive("e")
|
||||
public void execute() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
@Service(interfaceClass = Cloneable.class)
|
||||
@interface Service2 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
@Service2
|
||||
@interface Service3 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
@Service3
|
||||
@interface Service4 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
@Service4
|
||||
@interface Service5 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Inherited
|
||||
@Adaptive
|
||||
@interface MyAdaptive {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
}
|
||||
|
||||
@Service5
|
||||
static class B extends A {
|
||||
|
||||
@Adaptive("f")
|
||||
@Override
|
||||
public void execute() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@MyAdaptive
|
||||
static class C extends B {
|
||||
|
||||
}
|
||||
|
||||
private void assertADeclaredAnnotations(List<Annotation> annotations, int offset) {
|
||||
int size = 3 + offset;
|
||||
assertEquals(size, annotations.size());
|
||||
Service service = (Service) annotations.get(offset++);
|
||||
assertEquals("java.lang.CharSequence", service.interfaceName());
|
||||
assertEquals(CharSequence.class, service.interfaceClass());
|
||||
|
||||
com.alibaba.dubbo.config.annotation.Service s = (com.alibaba.dubbo.config.annotation.Service) annotations.get(offset++);
|
||||
assertEquals("java.lang.CharSequence", service.interfaceName());
|
||||
assertEquals(CharSequence.class, service.interfaceClass());
|
||||
|
||||
Adaptive adaptive = (Adaptive) annotations.get(offset++);
|
||||
assertArrayEquals(new String[]{"a", "b", "c"}, adaptive.value());
|
||||
}
|
||||
}
|
||||
|
|
@ -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.common.utils;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link MemberUtils} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class MemberUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testIsStatic() throws NoSuchMethodException {
|
||||
|
||||
assertFalse(isStatic(getClass().getMethod("testIsStatic")));
|
||||
assertTrue(isStatic(getClass().getMethod("staticMethod")));
|
||||
}
|
||||
|
||||
public static void staticMethod() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToBooleanConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToBooleanConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBooleanConverterTest {
|
||||
|
||||
private StringToBooleanConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToBooleanConverter) getExtensionLoader(Converter.class).getExtension("string-to-boolean");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertTrue(converter.convert("true"));
|
||||
assertTrue(converter.convert("true"));
|
||||
assertTrue(converter.convert("True"));
|
||||
assertFalse(converter.convert("a"));
|
||||
assertNull(converter.convert(""));
|
||||
assertNull(converter.convert(null));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToCharArrayConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToCharArrayConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCharArrayConverterTest {
|
||||
|
||||
private StringToCharArrayConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToCharArrayConverter) getExtensionLoader(Converter.class).getExtension("string-to-char-array");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, char[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertArrayEquals(new char[]{'1', '2', '3'}, converter.convert("123"));
|
||||
assertNull(converter.convert(null));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToCharacterConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToCharacterConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCharacterConverterTest {
|
||||
|
||||
private StringToCharacterConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToCharacterConverter) getExtensionLoader(Converter.class).getExtension("string-to-character");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Character.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals('t', converter.convert("t"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToDoubleConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToDoubleConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToDoubleConverterTest {
|
||||
|
||||
private StringToDoubleConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToDoubleConverter) getExtensionLoader(Converter.class).getExtension("string-to-double");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Double.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Double.valueOf("1.0"), converter.convert("1.0"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(NumberFormatException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToFloatConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToFloatConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToFloatConverterTest {
|
||||
|
||||
private StringToFloatConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToFloatConverter) getExtensionLoader(Converter.class).getExtension("string-to-float");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Float.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Float.valueOf("1.0"), converter.convert("1.0"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(NumberFormatException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToIntegerConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToIntegerConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToIntegerConverterTest {
|
||||
|
||||
private StringToIntegerConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToIntegerConverter) getExtensionLoader(Converter.class).getExtension("string-to-integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Integer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Integer.valueOf("1"), converter.convert("1"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(NumberFormatException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToLongConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToLongConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToLongConverterTest {
|
||||
|
||||
private StringToLongConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToLongConverter) getExtensionLoader(Converter.class).getExtension("string-to-long");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Long.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Long.valueOf("1"), converter.convert("1"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(NumberFormatException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToOptionalConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToOptionalConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToOptionalConverterTest {
|
||||
|
||||
private StringToOptionalConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToOptionalConverter) getExtensionLoader(Converter.class).getExtension("string-to-optional");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Optional.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Optional.of("1"), converter.convert("1"));
|
||||
assertEquals(Optional.empty(), converter.convert(null));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToShortConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToShortConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToShortConverterTest {
|
||||
|
||||
private StringToShortConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToShortConverter) getExtensionLoader(Converter.class).getExtension("string-to-short");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, Short.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals(Short.valueOf("1"), converter.convert("1"));
|
||||
assertNull(converter.convert(null));
|
||||
assertThrows(NumberFormatException.class, () -> {
|
||||
converter.convert("ttt");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.convert;
|
||||
|
||||
import org.apache.dubbo.common.convert.Converter;
|
||||
import org.apache.dubbo.common.convert.StringToStringConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link StringToStringConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToStringConverterTest {
|
||||
|
||||
private StringToStringConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = (StringToStringConverter) getExtensionLoader(Converter.class).getExtension("string-to-string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertEquals("1", converter.convert("1"));
|
||||
assertNull(converter.convert(null));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.StringToArrayConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.util.Objects.deepEquals;
|
||||
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 StringToArrayConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToArrayConverterTest {
|
||||
|
||||
private StringToArrayConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = new StringToArrayConverter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
assertTrue(converter.accept(String.class, char[].class));
|
||||
assertTrue(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
assertTrue(deepEquals(new Integer[]{123}, converter.convert("123", Integer[].class, Integer.class)));
|
||||
assertTrue(deepEquals(new Integer[]{1, 2, 3}, converter.convert("1,2,3", Integer[].class, null)));
|
||||
assertNull(converter.convert("", Integer[].class, null));
|
||||
assertNull(converter.convert(null, Integer[].class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToBlockingDequeConverter} Test
|
||||
*
|
||||
* @see BlockingDeque
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBlockingDequeConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-blocking-deque");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertTrue(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() throws NoSuchFieldException {
|
||||
|
||||
BlockingQueue<Integer> values = new LinkedBlockingDeque(asList(1, 2, 3));
|
||||
|
||||
BlockingDeque<Integer> result = (BlockingDeque<Integer>) converter.convert("1,2,3", BlockingDeque.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values = new LinkedBlockingDeque(asList(123));
|
||||
|
||||
result = (BlockingDeque<Integer>) converter.convert("123", BlockingDeque.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, null));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 5, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToBlockingQueueConverter} Test
|
||||
*
|
||||
* @see BlockingDeque
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToBlockingQueueConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-blocking-queue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertTrue(converter.accept(String.class, BlockingQueue.class));
|
||||
assertTrue(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertTrue(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
BlockingQueue values = new ArrayBlockingQueue(3);
|
||||
values.offer(1);
|
||||
values.offer(2);
|
||||
values.offer(3);
|
||||
|
||||
BlockingQueue<Integer> result = (BlockingQueue<Integer>) converter.convert("1,2,3", BlockingDeque.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values.clear();
|
||||
values.offer(123);
|
||||
|
||||
result = (BlockingQueue<Integer>) converter.convert("123", BlockingDeque.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, null));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToCollectionConverter;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToCollectionConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToCollectionConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-collection");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertTrue(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, List.class));
|
||||
assertTrue(converter.accept(String.class, AbstractList.class));
|
||||
assertTrue(converter.accept(String.class, ArrayList.class));
|
||||
assertTrue(converter.accept(String.class, LinkedList.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, Set.class));
|
||||
assertTrue(converter.accept(String.class, SortedSet.class));
|
||||
assertTrue(converter.accept(String.class, NavigableSet.class));
|
||||
assertTrue(converter.accept(String.class, TreeSet.class));
|
||||
assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, Queue.class));
|
||||
assertTrue(converter.accept(String.class, BlockingQueue.class));
|
||||
assertTrue(converter.accept(String.class, TransferQueue.class));
|
||||
assertTrue(converter.accept(String.class, Deque.class));
|
||||
assertTrue(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
List values = asList(1L, 2L, 3L);
|
||||
|
||||
Collection result = (Collection<Long>) converter.convert("1,2,3", Collection.class, Long.class);
|
||||
|
||||
assertEquals(values, result);
|
||||
|
||||
values = asList(123);
|
||||
|
||||
result = (Collection<Integer>) converter.convert("123", Collection.class, Integer.class);
|
||||
|
||||
assertEquals(values, result);
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, Integer.class));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 1, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToDequeConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToDequeConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToDequeConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-deque");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertTrue(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertTrue(converter.accept(String.class, Deque.class));
|
||||
assertTrue(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
Deque values = new ArrayDeque(asList(1, 2, 3));
|
||||
|
||||
Deque result = (Deque) converter.convert("1,2,3", Deque.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values = new ArrayDeque(asList("123"));
|
||||
|
||||
result = (Deque) converter.convert("123", Deque.class, String.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToListConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToListConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-list");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, List.class));
|
||||
assertTrue(converter.accept(String.class, AbstractList.class));
|
||||
assertTrue(converter.accept(String.class, LinkedList.class));
|
||||
assertTrue(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertFalse(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
List values = asList(1, 2, 3);
|
||||
|
||||
List result = (List<Integer>) converter.convert("1,2,3", List.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values = asList("123");
|
||||
|
||||
result = (List<String>) converter.convert("123", List.class, String.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToListConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToNavigableSetConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-navigable-set");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertTrue(converter.accept(String.class, NavigableSet.class));
|
||||
assertTrue(converter.accept(String.class, TreeSet.class));
|
||||
assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertFalse(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
Set values = new TreeSet(asList(1, 2, 3));
|
||||
|
||||
NavigableSet result = (NavigableSet) converter.convert("1,2,3", List.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values = new TreeSet(asList("123"));
|
||||
|
||||
result = (NavigableSet) converter.convert("123", NavigableSet.class, String.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 4, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.StringToQueueConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
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 StringToQueueConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToQueueConverterTest {
|
||||
|
||||
private StringToQueueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = new StringToQueueConverter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertTrue(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, Queue.class));
|
||||
assertTrue(converter.accept(String.class, BlockingQueue.class));
|
||||
assertTrue(converter.accept(String.class, TransferQueue.class));
|
||||
assertTrue(converter.accept(String.class, Deque.class));
|
||||
assertTrue(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
Queue values = new ArrayDeque(asList(1.0, 2.0, 3.0));
|
||||
|
||||
Queue result = (Queue<Double>) converter.convert("1.0,2.0,3.0", Queue.class, Double.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values.clear();
|
||||
values.add(123);
|
||||
|
||||
result = (Queue) converter.convert("123", Queue.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.StringToSetConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
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 StringToSetConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToSetConverterTest {
|
||||
|
||||
private StringToSetConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = new StringToSetConverter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertTrue(converter.accept(String.class, Set.class));
|
||||
assertTrue(converter.accept(String.class, SortedSet.class));
|
||||
assertTrue(converter.accept(String.class, NavigableSet.class));
|
||||
assertTrue(converter.accept(String.class, TreeSet.class));
|
||||
assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertFalse(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
Set values = new HashSet(asList(1.0, 2.0, 3.0));
|
||||
|
||||
Set result = (Set<Double>) converter.convert("1.0,2.0,3.0", Queue.class, Double.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values.clear();
|
||||
values.add(123);
|
||||
|
||||
result = (Set) converter.convert("123", Queue.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToListConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToSortedSetConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-sorted-set");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertTrue(converter.accept(String.class, SortedSet.class));
|
||||
assertTrue(converter.accept(String.class, NavigableSet.class));
|
||||
assertTrue(converter.accept(String.class, TreeSet.class));
|
||||
assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, TransferQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertFalse(converter.accept(String.class, BlockingDeque.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
Set values = new TreeSet(asList(1, 2, 3));
|
||||
|
||||
SortedSet result = (SortedSet) converter.convert("1,2,3", List.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values = new TreeSet(asList("123"));
|
||||
|
||||
result = (SortedSet) converter.convert("123", NavigableSet.class, String.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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.convert.multiple;
|
||||
|
||||
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
|
||||
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.TransferQueue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
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 StringToListConverter} Test
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class StringToTransferQueueConverterTest {
|
||||
|
||||
private MultiValueConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-transfer-queue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
|
||||
assertFalse(converter.accept(String.class, Collection.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, List.class));
|
||||
assertFalse(converter.accept(String.class, AbstractList.class));
|
||||
assertFalse(converter.accept(String.class, LinkedList.class));
|
||||
assertFalse(converter.accept(String.class, ArrayList.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Set.class));
|
||||
assertFalse(converter.accept(String.class, SortedSet.class));
|
||||
assertFalse(converter.accept(String.class, NavigableSet.class));
|
||||
assertFalse(converter.accept(String.class, TreeSet.class));
|
||||
assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
|
||||
|
||||
assertFalse(converter.accept(String.class, Queue.class));
|
||||
assertFalse(converter.accept(String.class, BlockingQueue.class));
|
||||
assertFalse(converter.accept(String.class, Deque.class));
|
||||
assertFalse(converter.accept(String.class, BlockingDeque.class));
|
||||
assertTrue(converter.accept(String.class, TransferQueue.class));
|
||||
|
||||
assertFalse(converter.accept(null, char[].class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, String.class));
|
||||
assertFalse(converter.accept(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
TransferQueue values = new LinkedTransferQueue(asList(1, 2, 3));
|
||||
|
||||
TransferQueue result = (TransferQueue) converter.convert("1,2,3", List.class, Integer.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
values.clear();
|
||||
|
||||
values.addAll(asList("123"));
|
||||
|
||||
result = (TransferQueue) converter.convert("123", NavigableSet.class, String.class);
|
||||
|
||||
assertTrue(CollectionUtils.equals(values, result));
|
||||
|
||||
assertNull(converter.convert(null, Collection.class, Integer.class));
|
||||
assertNull(converter.convert("", Collection.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSourceType() {
|
||||
assertEquals(String.class, converter.getSourceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
assertEquals(Integer.MAX_VALUE - 4, converter.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,6 @@ import org.apache.dubbo.service.DemoService;
|
|||
import org.apache.dubbo.service.DemoServiceImpl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
@ -184,7 +183,7 @@ public class GenericServiceTest {
|
|||
}
|
||||
}
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String, java.lang.String>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), "org.apache.dubbo.service.ComplexObject$InnerObject");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
|
|||
* @export
|
||||
*/
|
||||
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
|
||||
ApplicationContextAware, BeanNameAware,
|
||||
ApplicationEventPublisherAware {
|
||||
ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 213195494150089726L;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,20 @@
|
|||
<scope>test</scope>
|
||||
</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>
|
||||
|
|
@ -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.definition;
|
||||
|
||||
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
|
||||
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link MethodDefinition} Builder based on Java Reflection
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class MethodDefinitionBuilder {
|
||||
|
||||
private final TypeDefinitionBuilder builder;
|
||||
|
||||
public MethodDefinitionBuilder(TypeDefinitionBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public MethodDefinitionBuilder() {
|
||||
this.builder = new TypeDefinitionBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the instance of {@link MethodDefinition}
|
||||
*
|
||||
* @param method {@link Method}
|
||||
* @return non-null
|
||||
*/
|
||||
public MethodDefinition build(Method method) {
|
||||
|
||||
MethodDefinition md = new MethodDefinition();
|
||||
md.setName(method.getName());
|
||||
|
||||
// Process the parameters
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
Type[] genericParamTypes = method.getGenericParameterTypes();
|
||||
|
||||
int paramSize = paramTypes.length;
|
||||
String[] parameterTypes = new String[paramSize];
|
||||
List<TypeDefinition> parameters = new ArrayList<>(paramSize);
|
||||
for (int i = 0; i < paramSize; i++) {
|
||||
TypeDefinition parameter = builder.build(genericParamTypes[i], paramTypes[i]);
|
||||
parameterTypes[i] = parameter.getType();
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
md.setParameterTypes(parameterTypes);
|
||||
md.setParameters(parameters);
|
||||
|
||||
// Process return type.
|
||||
TypeDefinition td = builder.build(method.getGenericReturnType(), method.getReturnType());
|
||||
md.setReturnType(td.getType());
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,6 +29,8 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.isSimpleType;
|
||||
|
||||
/**
|
||||
* 2015/1/27.
|
||||
*/
|
||||
|
|
@ -55,7 +57,7 @@ public class TypeDefinitionBuilder {
|
|||
td = DefaultTypeBuilder.build(clazz, typeCache);
|
||||
td.setTypeBuilderName(DefaultTypeBuilder.class.getName());
|
||||
}
|
||||
if (clazz.equals(String.class)) {
|
||||
if (isSimpleType(clazz)) { // changed since 2.7.6
|
||||
td.setProperties(null);
|
||||
}
|
||||
return td;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ import java.text.MessageFormat;
|
|||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.utils.StringUtils.replace;
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.getRawClass;
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.isClass;
|
||||
import static org.apache.dubbo.common.utils.TypeUtils.isParameterizedType;
|
||||
|
||||
/**
|
||||
* 2015/1/27.
|
||||
*/
|
||||
|
|
@ -46,23 +51,37 @@ public class MapTypeBuilder implements TypeBuilder {
|
|||
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArgs == null || actualTypeArgs.length != 2) {
|
||||
int actualTypeArgsLength = actualTypeArgs == null ? 0 : actualTypeArgs.length;
|
||||
|
||||
if (actualTypeArgsLength != 2) {
|
||||
throw new IllegalArgumentException(MessageFormat.format(
|
||||
"[ServiceDefinitionBuilder] Map type [{0}] with unexpected amount of arguments [{1}]."
|
||||
+ Arrays.toString(actualTypeArgs), type, actualTypeArgs));
|
||||
}
|
||||
|
||||
for (Type actualType : actualTypeArgs) {
|
||||
if (actualType instanceof ParameterizedType) {
|
||||
// Change since 2.7.6
|
||||
/**
|
||||
* Replacing <code>", "</code> to <code>","</code> will not change the semantic of
|
||||
* {@link ParameterizedType#toString()}
|
||||
* @see sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
|
||||
*/
|
||||
String mapType = replace(type.toString(), ", ", ",");
|
||||
|
||||
TypeDefinition typeDefinition = new TypeDefinition(mapType);
|
||||
|
||||
for (int i = 0; i < actualTypeArgsLength; i++) {
|
||||
Type actualType = actualTypeArgs[i];
|
||||
TypeDefinition item = null;
|
||||
Class<?> rawType = getRawClass(actualType);
|
||||
if (isParameterizedType(actualType)) {
|
||||
// Nested collection or map.
|
||||
Class<?> rawType = (Class<?>) ((ParameterizedType) actualType).getRawType();
|
||||
TypeDefinitionBuilder.build(actualType, rawType, typeCache);
|
||||
} else if (actualType instanceof Class<?>) {
|
||||
Class<?> actualClass = (Class<?>) actualType;
|
||||
TypeDefinitionBuilder.build(null, actualClass, typeCache);
|
||||
item = TypeDefinitionBuilder.build(actualType, rawType, typeCache);
|
||||
} else if (isClass(actualType)) {
|
||||
item = TypeDefinitionBuilder.build(null, rawType, typeCache);
|
||||
}
|
||||
typeDefinition.getItems().add(item);
|
||||
}
|
||||
|
||||
return new TypeDefinition(type.toString());
|
||||
return typeDefinition;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getValue;
|
||||
import static org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
|
||||
|
||||
/**
|
||||
* The abstract {@link AnnotatedMethodParameterProcessor} implementation
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public abstract class AbstractAnnotatedMethodParameterProcessor implements AnnotatedMethodParameterProcessor {
|
||||
|
||||
@Override
|
||||
public void process(Annotation annotation, Parameter parameter, int parameterIndex, Method method,
|
||||
Class<?> serviceType, Class<?> serviceInterfaceClass, RestMethodMetadata restMethodMetadata) {
|
||||
String annotationValue = getAnnotationValue(annotation, parameter, parameterIndex);
|
||||
String defaultValue = getDefaultValue(annotation, parameter, parameterIndex);
|
||||
process(annotationValue, defaultValue, annotation, parameter, parameterIndex, method, restMethodMetadata);
|
||||
}
|
||||
|
||||
protected String getAnnotationValue(Annotation annotation, Parameter parameter, int parameterIndex) {
|
||||
return getValue(annotation);
|
||||
}
|
||||
|
||||
protected String getDefaultValue(Annotation annotation, Parameter parameter, int parameterIndex) {
|
||||
return buildDefaultValue(parameterIndex);
|
||||
}
|
||||
|
||||
protected abstract void process(String annotationValue, String defaultValue, Annotation annotation, Object parameter,
|
||||
int parameterIndex, Method method, RestMethodMetadata restMethodMetadata);
|
||||
}
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* 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.MethodComparator;
|
||||
import org.apache.dubbo.common.utils.ServiceAnnotationResolver;
|
||||
import org.apache.dubbo.config.annotation.Service;
|
||||
import org.apache.dubbo.metadata.definition.MethodDefinitionBuilder;
|
||||
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.sort;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
|
||||
import static org.apache.dubbo.common.function.ThrowableFunction.execute;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnyAnnotationPresent;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.forName;
|
||||
import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
|
||||
import static org.apache.dubbo.common.utils.MethodUtils.excludedDeclaredClass;
|
||||
import static org.apache.dubbo.common.utils.MethodUtils.getAllMethods;
|
||||
import static org.apache.dubbo.common.utils.MethodUtils.overrides;
|
||||
|
||||
/**
|
||||
* The abstract {@link ServiceRestMetadataResolver} class to provider some template methods assemble the instance of
|
||||
* {@link ServiceRestMetadata} will extended by the sub-classes.
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public abstract class AbstractServiceRestMetadataResolver implements ServiceRestMetadataResolver {
|
||||
|
||||
private final Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap;
|
||||
|
||||
public AbstractServiceRestMetadataResolver() {
|
||||
this.parameterProcessorsMap = loadAnnotatedMethodParameterProcessors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean supports(Class<?> serviceType) {
|
||||
return isImplementedInterface(serviceType) && isServiceAnnotationPresent(serviceType) && supports0(serviceType);
|
||||
}
|
||||
|
||||
protected final boolean isImplementedInterface(Class<?> serviceType) {
|
||||
return !getAllInterfaces(serviceType).isEmpty();
|
||||
}
|
||||
|
||||
protected final boolean isServiceAnnotationPresent(Class<?> serviceType) {
|
||||
return isAnyAnnotationPresent(serviceType, Service.class, com.alibaba.dubbo.config.annotation.Service.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* internal support method
|
||||
*
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @return If supports, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
protected abstract boolean supports0(Class<?> serviceType);
|
||||
|
||||
@Override
|
||||
public final ServiceRestMetadata resolve(Class<?> serviceType) {
|
||||
|
||||
ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata();
|
||||
|
||||
// Process ServiceRestMetadata
|
||||
processServiceRestMetadata(serviceRestMetadata, serviceType);
|
||||
|
||||
// Process RestMethodMetadata
|
||||
processAllRestMethodMetadata(serviceRestMetadata, serviceType);
|
||||
|
||||
return serviceRestMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the service type including the sub-routines:
|
||||
* <ul>
|
||||
* <li>{@link ServiceRestMetadata#setServiceInterface(String)}</li>
|
||||
* <li>{@link ServiceRestMetadata#setVersion(String)}</li>
|
||||
* <li>{@link ServiceRestMetadata#setGroup(String)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param serviceRestMetadata {@link ServiceRestMetadata}
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
*/
|
||||
protected void processServiceRestMetadata(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
|
||||
ServiceAnnotationResolver resolver = new ServiceAnnotationResolver(serviceType);
|
||||
serviceRestMetadata.setServiceInterface(resolver.resolveInterfaceClassName());
|
||||
serviceRestMetadata.setVersion(resolver.resolveVersion());
|
||||
serviceRestMetadata.setGroup(resolver.resolveGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all {@link RestMethodMetadata}
|
||||
*
|
||||
* @param serviceRestMetadata {@link ServiceRestMetadata}
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
*/
|
||||
protected void processAllRestMethodMetadata(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
|
||||
Class<?> serviceInterfaceClass = resolveServiceInterfaceClass(serviceRestMetadata, serviceType);
|
||||
Map<Method, Method> serviceMethodsMap = resolveServiceMethodsMap(serviceType, serviceInterfaceClass);
|
||||
for (Map.Entry<Method, Method> entry : serviceMethodsMap.entrySet()) {
|
||||
// try the overrider method first
|
||||
Method serviceMethod = entry.getKey();
|
||||
// If failed, it indicates the overrider method does not contain metadata , then try the declared method
|
||||
if (!processRestMethodMetadata(serviceMethod, serviceType, serviceInterfaceClass, serviceRestMetadata.getMeta()::add)) {
|
||||
Method declaredServiceMethod = entry.getValue();
|
||||
processRestMethodMetadata(declaredServiceMethod, serviceType, serviceInterfaceClass,
|
||||
serviceRestMetadata.getMeta()::add);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a map of all public services methods from the specified service type and its interface class, whose key is the
|
||||
* declared method, and the value is the overrider method
|
||||
*
|
||||
* @param serviceType the service interface implementation class
|
||||
* @param serviceInterfaceClass the service interface class
|
||||
* @return non-null read-only {@link Map}
|
||||
*/
|
||||
protected Map<Method, Method> resolveServiceMethodsMap(Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
Map<Method, Method> serviceMethodsMap = new LinkedHashMap<>();
|
||||
// exclude the public methods declared in java.lang.Object.class
|
||||
List<Method> declaredServiceMethods = new ArrayList<>(getAllMethods(serviceInterfaceClass, excludedDeclaredClass(Object.class)));
|
||||
List<Method> serviceMethods = new ArrayList<>(getAllMethods(serviceType, excludedDeclaredClass(Object.class)));
|
||||
|
||||
// sort methods
|
||||
sort(declaredServiceMethods, MethodComparator.INSTANCE);
|
||||
sort(serviceMethods, MethodComparator.INSTANCE);
|
||||
|
||||
for (Method declaredServiceMethod : declaredServiceMethods) {
|
||||
for (Method serviceMethod : serviceMethods) {
|
||||
if (overrides(serviceMethod, declaredServiceMethod)) {
|
||||
serviceMethodsMap.put(serviceMethod, declaredServiceMethod);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// make them to be read-only
|
||||
return unmodifiableMap(serviceMethodsMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the class of Dubbo Service interface
|
||||
*
|
||||
* @param serviceRestMetadata {@link ServiceRestMetadata}
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @return non-null
|
||||
* @throws RuntimeException If the class is not found, the {@link RuntimeException} wraps the cause will be thrown
|
||||
*/
|
||||
protected Class<?> resolveServiceInterfaceClass(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
|
||||
return execute(serviceType.getClassLoader(), classLoader -> {
|
||||
String serviceInterface = serviceRestMetadata.getServiceInterface();
|
||||
return forName(serviceInterface, classLoader);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the single {@link RestMethodMetadata} by the specified {@link Consumer} if present
|
||||
*
|
||||
* @param serviceMethod Dubbo Service method
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @param metadataToProcess {@link RestMethodMetadata} to process if present
|
||||
* @return if processed successfully, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
protected boolean processRestMethodMetadata(Method serviceMethod, Class<?> serviceType,
|
||||
Class<?> serviceInterfaceClass,
|
||||
Consumer<RestMethodMetadata> metadataToProcess) {
|
||||
|
||||
if (!isRestCapableMethod(serviceMethod, serviceType, serviceInterfaceClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String requestPath = resolveRequestPath(serviceMethod, serviceType, serviceInterfaceClass); // requestPath is required
|
||||
|
||||
if (requestPath == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String requestMethod = resolveRequestMethod(serviceMethod, serviceType, serviceInterfaceClass); // requestMethod is required
|
||||
|
||||
if (requestMethod == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RestMethodMetadata metadata = new RestMethodMetadata();
|
||||
|
||||
MethodDefinition methodDefinition = resolveMethodDefinition(serviceMethod, serviceType, serviceInterfaceClass);
|
||||
// Set MethodDefinition
|
||||
metadata.setMethod(methodDefinition);
|
||||
|
||||
// process the annotated method parameters
|
||||
processAnnotatedMethodParameters(serviceMethod, serviceType, serviceInterfaceClass, metadata);
|
||||
|
||||
// process produces
|
||||
Set<String> produces = new LinkedHashSet<>();
|
||||
processProduces(serviceMethod, serviceType, serviceInterfaceClass, produces);
|
||||
|
||||
// process consumes
|
||||
Set<String> consumes = new LinkedHashSet<>();
|
||||
processConsumes(serviceMethod, serviceType, serviceInterfaceClass, consumes);
|
||||
|
||||
// Initialize RequestMetadata
|
||||
RequestMetadata request = metadata.getRequest();
|
||||
request.setPath(requestPath);
|
||||
request.setMethod(requestMethod);
|
||||
request.setProduces(produces);
|
||||
request.setConsumes(consumes);
|
||||
|
||||
// Post-Process
|
||||
postResolveRestMethodMetadata(serviceMethod, serviceType, serviceInterfaceClass, metadata);
|
||||
|
||||
// Accept RestMethodMetadata
|
||||
metadataToProcess.accept(metadata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the service method is capable of REST or not?
|
||||
*
|
||||
* @param serviceMethod Dubbo Service method
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @return If capable, return <code>true</code>
|
||||
*/
|
||||
protected abstract boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?>
|
||||
serviceInterfaceClass);
|
||||
|
||||
/**
|
||||
* Resolve the request method
|
||||
*
|
||||
* @param serviceMethod Dubbo Service method
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @return if can't be resolve, return <code>null</code>
|
||||
*/
|
||||
protected abstract String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?>
|
||||
serviceInterfaceClass);
|
||||
|
||||
/**
|
||||
* Resolve the request path
|
||||
*
|
||||
* @param serviceMethod Dubbo Service method
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @return if can't be resolve, return <code>null</code>
|
||||
*/
|
||||
protected abstract String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?>
|
||||
serviceInterfaceClass);
|
||||
|
||||
/**
|
||||
* Resolve the {@link MethodDefinition}
|
||||
*
|
||||
* @param serviceMethod Dubbo Service method
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @return if can't be resolve, return <code>null</code>
|
||||
* @see MethodDefinitionBuilder
|
||||
*/
|
||||
protected MethodDefinition resolveMethodDefinition(Method serviceMethod, Class<?> serviceType,
|
||||
Class<?> serviceInterfaceClass) {
|
||||
MethodDefinitionBuilder builder = new MethodDefinitionBuilder();
|
||||
return builder.build(serviceMethod);
|
||||
}
|
||||
|
||||
private void processAnnotatedMethodParameters(Method serviceMethod, Class<?> serviceType,
|
||||
Class<?> serviceInterfaceClass, RestMethodMetadata metadata) {
|
||||
int paramCount = serviceMethod.getParameterCount();
|
||||
Parameter[] parameters = serviceMethod.getParameters();
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
Parameter parameter = parameters[i];
|
||||
// Add indexed parameter name
|
||||
metadata.addIndexToName(i,parameter.getName());
|
||||
processAnnotatedMethodParameter(parameter, i, serviceMethod, serviceType, serviceInterfaceClass, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnnotatedMethodParameter(Parameter parameter, int parameterIndex, Method serviceMethod,
|
||||
Class<?> serviceType, Class<?> serviceInterfaceClass,
|
||||
RestMethodMetadata metadata) {
|
||||
Annotation[] annotations = parameter.getAnnotations();
|
||||
for (Annotation annotation : annotations) {
|
||||
String annotationType = annotation.annotationType().getName();
|
||||
parameterProcessorsMap.getOrDefault(annotationType, emptyList())
|
||||
.forEach(processor -> {
|
||||
processor.process(annotation, parameter, parameterIndex, serviceMethod, serviceType,
|
||||
serviceInterfaceClass, metadata);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void processProduces(Method serviceMethod, Class<?> serviceType, Class<?>
|
||||
serviceInterfaceClass,
|
||||
Set<String> produces);
|
||||
|
||||
protected abstract void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?>
|
||||
serviceInterfaceClass,
|
||||
Set<String> consumes);
|
||||
|
||||
protected void postResolveRestMethodMetadata(Method serviceMethod, Class<?> serviceType,
|
||||
Class<?> serviceInterfaceClass, RestMethodMetadata metadata) {
|
||||
}
|
||||
|
||||
private static Map<String, List<AnnotatedMethodParameterProcessor>> loadAnnotatedMethodParameterProcessors() {
|
||||
Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = new LinkedHashMap<>();
|
||||
getExtensionLoader(AnnotatedMethodParameterProcessor.class)
|
||||
.getSupportedExtensionInstances()
|
||||
.forEach(processor -> {
|
||||
List<AnnotatedMethodParameterProcessor> processors =
|
||||
parameterProcessorsMap.computeIfAbsent(processor.getAnnotationType(), k -> new LinkedList<>());
|
||||
processors.add(processor);
|
||||
});
|
||||
return parameterProcessorsMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.common.lang.Prioritized;
|
||||
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
/**
|
||||
* The interface to process the annotated method parameter
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@SPI
|
||||
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 Annotation the target annotation} whose type is {@link #getAnnotationType()}
|
||||
* @param parameter the method parameter
|
||||
* @param parameterIndex the index of method parameter
|
||||
* @param method {@link Method method that parameter belongs to}
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @param serviceInterfaceClass The type of Dubbo Service interface
|
||||
* @param restMethodMetadata {@link RestMethodMetadata the metadata is used to update}
|
||||
*/
|
||||
void process(Annotation annotation, Parameter parameter, int parameterIndex, Method method,
|
||||
Class<?> serviceType, Class<?> serviceInterfaceClass, RestMethodMetadata restMethodMetadata);
|
||||
|
||||
/**
|
||||
* Build the default value
|
||||
*
|
||||
* @param parameterIndex the index of parameter
|
||||
* @return the placeholder
|
||||
*/
|
||||
static String buildDefaultValue(int parameterIndex) {
|
||||
return "{" + parameterIndex + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.metadata.rest;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.apache.dubbo.common.function.ThrowableAction.execute;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.METADATA_ENCODING;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SERVICE_REST_METADATA_RESOURCE_PATH;
|
||||
|
||||
/**
|
||||
* Class-Path based {@link ServiceRestMetadataReader} implementation
|
||||
*
|
||||
* @see ServiceRestMetadataReader
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class ClassPathServiceRestMetadataReader implements ServiceRestMetadataReader {
|
||||
|
||||
private final String serviceRestMetadataJsonResoucePath;
|
||||
|
||||
public ClassPathServiceRestMetadataReader() {
|
||||
this(SERVICE_REST_METADATA_RESOURCE_PATH);
|
||||
}
|
||||
|
||||
public ClassPathServiceRestMetadataReader(String serviceRestMetadataJsonResoucePath) {
|
||||
this.serviceRestMetadataJsonResoucePath = serviceRestMetadataJsonResoucePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceRestMetadata> read() {
|
||||
|
||||
List<ServiceRestMetadata> serviceRestMetadataList = new LinkedList<>();
|
||||
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
|
||||
execute(() -> {
|
||||
Enumeration<URL> resources = classLoader.getResources(serviceRestMetadataJsonResoucePath);
|
||||
Gson gson = new Gson();
|
||||
while (resources.hasMoreElements()) {
|
||||
URL resource = resources.nextElement();
|
||||
InputStream inputStream = resource.openStream();
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonElement jsonElement = parser.parse(new InputStreamReader(inputStream, METADATA_ENCODING));
|
||||
if (jsonElement.isJsonArray()) {
|
||||
JsonArray jsonArray = jsonElement.getAsJsonArray();
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JsonElement childJsonElement = jsonArray.get(i);
|
||||
ServiceRestMetadata serviceRestMetadata = gson.fromJson(childJsonElement, ServiceRestMetadata.class);
|
||||
serviceRestMetadataList.add(serviceRestMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return unmodifiableList(serviceRestMetadataList);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* The default implementation {@link ServiceRestMetadataResolver}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class DefaultServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
|
||||
|
||||
@Override
|
||||
protected boolean supports0(Class<?> serviceType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> produces) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> consumes) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* 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.HttpUtils.normalizePath;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
|
||||
|
||||
/**
|
||||
* The metadata class for REST request
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
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 getFirst(params, name);
|
||||
}
|
||||
|
||||
public String getHeader(String name) {
|
||||
return 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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The REST Metadata Constants definition interface
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface RestMetadataConstants {
|
||||
|
||||
/**
|
||||
* The encoding of metadata
|
||||
*/
|
||||
String METADATA_ENCODING = "UTF-8";
|
||||
|
||||
/**
|
||||
* {@link ServiceRestMetadata} Resource PATH
|
||||
*/
|
||||
String SERVICE_REST_METADATA_RESOURCE_PATH = "META-INF/dubbo/service-rest-metadata.json";
|
||||
|
||||
/**
|
||||
* JAX-RS
|
||||
*/
|
||||
interface JAX_RS {
|
||||
|
||||
/**
|
||||
* The annotation class name of @Path
|
||||
*/
|
||||
String PATH_ANNOTATION_CLASS_NAME = "javax.ws.rs.Path";
|
||||
|
||||
/**
|
||||
* The annotation class name of @HttpMethod
|
||||
*/
|
||||
String HTTP_METHOD_ANNOTATION_CLASS_NAME = "javax.ws.rs.HttpMethod";
|
||||
|
||||
/**
|
||||
* The annotation class name of @Produces
|
||||
*/
|
||||
String PRODUCES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Produces";
|
||||
|
||||
/**
|
||||
* The annotation class name of @Consumes
|
||||
*/
|
||||
String CONSUMES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Consumes";
|
||||
|
||||
/**
|
||||
* The annotation class name of @DefaultValue
|
||||
*/
|
||||
String DEFAULT_VALUE_ANNOTATION_CLASS_NAME = "javax.ws.rs.DefaultValue";
|
||||
|
||||
/**
|
||||
* The annotation class name of @FormParam
|
||||
*/
|
||||
String FORM_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.FormParam";
|
||||
|
||||
/**
|
||||
* The annotation class name of @HeaderParam
|
||||
*/
|
||||
String HEADER_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.HeaderParam";
|
||||
|
||||
/**
|
||||
* The annotation class name of @MatrixParam
|
||||
*/
|
||||
String MATRIX_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.MatrixParam";
|
||||
|
||||
/**
|
||||
* The annotation class name of @QueryParam
|
||||
*/
|
||||
String QUERY_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.QueryParam";
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring MVC
|
||||
*/
|
||||
interface SPRING_MVC {
|
||||
|
||||
/**
|
||||
* The annotation class name of @Controller
|
||||
*/
|
||||
String CONTROLLER_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Controller";
|
||||
|
||||
/**
|
||||
* The annotation class name of @RequestMapping
|
||||
*/
|
||||
String REQUEST_MAPPING_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestMapping";
|
||||
|
||||
/**
|
||||
* The annotation class name of @RequestHeader
|
||||
*/
|
||||
String REQUEST_HEADER_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestHeader";
|
||||
|
||||
/**
|
||||
* The annotation class name of @RequestParam
|
||||
*/
|
||||
String REQUEST_PARAM_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestParam";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.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.6
|
||||
*/
|
||||
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) {
|
||||
if (index == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name.startsWith("arg") && name.endsWith(index.toString())) {
|
||||
// Ignore this value because of the Java byte-code without the metadata of method parameters
|
||||
return;
|
||||
}
|
||||
|
||||
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(getFormParams(), that.getFormParams()) &&
|
||||
Objects.equals(getIndexToEncoded(), that.getIndexToEncoded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getMethod(), getRequest(), getUrlIndex(), getBodyIndex(), getHeaderMapIndex(), getBodyType(), 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.6
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.metadata.rest;
|
||||
|
||||
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An interface to read {@link ServiceRestMetadata}
|
||||
*
|
||||
* @see ServiceRestMetadata
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@SPI
|
||||
public interface ServiceRestMetadataReader {
|
||||
|
||||
/**
|
||||
* Read the instances of {@link ServiceRestMetadata}
|
||||
*
|
||||
* @return non-null
|
||||
*/
|
||||
List<ServiceRestMetadata> read();
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The interface to resolve the {@link ServiceRestMetadata REST metadata} from the specified
|
||||
* Dubbo Service interface or type.
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public interface ServiceRestMetadataResolver {
|
||||
|
||||
/**
|
||||
* Support to resolve {@link ServiceRestMetadata REST metadata} or not
|
||||
*
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @return If supports, return <code>true</code>, or <code>false</code>
|
||||
*/
|
||||
boolean supports(Class<?> serviceType);
|
||||
|
||||
/**
|
||||
* Resolve the {@link ServiceRestMetadata REST metadata} from the specified
|
||||
* Dubbo Service interface or type
|
||||
*
|
||||
* @param serviceType Dubbo Service interface or type
|
||||
* @return
|
||||
*/
|
||||
ServiceRestMetadata resolve(Class<?> serviceType);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.metadata.rest.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.RequestMetadata;
|
||||
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
|
||||
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @DefaultValue
|
||||
* *
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(String annotationValue, String defaultValue, Annotation annotation, Object parameter,
|
||||
int parameterIndex, Method 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.FORM_PARAM_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @FormParam
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class FormParamParameterProcessor extends ParamAnnotationParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return FORM_PARAM_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.RequestMetadata;
|
||||
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.HEADER_PARAM_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @HeaderParam
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class HeaderParamParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return HEADER_PARAM_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(String headerName, String defaultValue, Annotation annotation, Object parameter,
|
||||
int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
|
||||
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
|
||||
// Add the placeholder as header value
|
||||
requestMetadata.addHeader(headerName, buildDefaultValue(parameterIndex));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver;
|
||||
import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findMetaAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getValue;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
|
||||
import static org.apache.dubbo.common.utils.HttpUtils.buildPath;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.CONSUMES_ANNOTATION_CLASS_NAME;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.HTTP_METHOD_ANNOTATION_CLASS_NAME;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.PATH_ANNOTATION_CLASS_NAME;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.PRODUCES_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* JAX-RS {@link ServiceRestMetadataResolver} implementation
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class JAXRSServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
|
||||
|
||||
@Override
|
||||
protected boolean supports0(Class<?> serviceType) {
|
||||
return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
return isAnnotationPresent(serviceMethod, HTTP_METHOD_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
Annotation httpMethod = findMetaAnnotation(serviceMethod, HTTP_METHOD_ANNOTATION_CLASS_NAME);
|
||||
return getValue(httpMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
String requestBasePath = resolveRequestPathFromType(serviceType, serviceInterfaceClass);
|
||||
String requestRelativePath = resolveRequestPathFromMethod(serviceMethod);
|
||||
return buildPath(requestBasePath, requestRelativePath);
|
||||
}
|
||||
|
||||
private String resolveRequestPathFromType(Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
Annotation path = findAnnotation(serviceType, PATH_ANNOTATION_CLASS_NAME);
|
||||
if (path == null) {
|
||||
path = findAnnotation(serviceInterfaceClass, PATH_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
return getValue(path);
|
||||
}
|
||||
|
||||
private String resolveRequestPathFromMethod(Method serviceMethod) {
|
||||
Annotation path = findAnnotation(serviceMethod, PATH_ANNOTATION_CLASS_NAME);
|
||||
return getValue(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass,
|
||||
Set<String> produces) {
|
||||
addAnnotationValues(serviceMethod, PRODUCES_ANNOTATION_CLASS_NAME, produces);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass,
|
||||
Set<String> consumes) {
|
||||
addAnnotationValues(serviceMethod, CONSUMES_ANNOTATION_CLASS_NAME, consumes);
|
||||
}
|
||||
|
||||
private void addAnnotationValues(Method serviceMethod, String annotationAttributeName, Set<String> result) {
|
||||
Annotation annotation = findAnnotation(serviceMethod, annotationAttributeName);
|
||||
String[] value = getValue(annotation);
|
||||
if (value != null) {
|
||||
Stream.of(value).forEach(result::add);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.MATRIX_PARAM_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @MatrixParam
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class MatrixParamParameterProcessor extends ParamAnnotationParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return MATRIX_PARAM_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.RequestMetadata;
|
||||
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The abstract {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @*Param
|
||||
*/
|
||||
public abstract class ParamAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
|
||||
|
||||
@Override
|
||||
protected void process(String name, String defaultValue, Annotation annotation, Object parameter,
|
||||
int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
|
||||
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
|
||||
requestMetadata.addParam(name, defaultValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.jaxrs;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.QUERY_PARAM_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @QueryParam
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class QueryParamParameterProcessor extends ParamAnnotationParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return QUERY_PARAM_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest.springmvc;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
|
||||
|
||||
/**
|
||||
* The abstract {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @Request*
|
||||
*/
|
||||
public abstract class AbstractRequestAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
|
||||
|
||||
@Override
|
||||
protected String getAnnotationValue(Annotation annotation, Parameter 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.getName();
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultValue(Annotation annotation, Parameter 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.springmvc;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_HEADER_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestHeader
|
||||
*/
|
||||
public class RequestHeaderParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return REQUEST_HEADER_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(String name, String defaultValue, Annotation annotation, Object parameter,
|
||||
int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
|
||||
restMethodMetadata.getRequest().addHeader(name, defaultValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.springmvc;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
|
||||
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_PARAM_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestParam
|
||||
*/
|
||||
public class RequestParamParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
|
||||
|
||||
@Override
|
||||
public String getAnnotationType() {
|
||||
return REQUEST_PARAM_ANNOTATION_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(String name, String defaultValue, Annotation annotation, Object parameter, int parameterIndex,
|
||||
Method method, RestMethodMetadata restMethodMetadata) {
|
||||
restMethodMetadata.getRequest().addParam(name, defaultValue);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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.springmvc;
|
||||
|
||||
import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver;
|
||||
import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
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.utils.AnnotationUtils.findAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.findMetaAnnotation;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
|
||||
import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
|
||||
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
|
||||
import static org.apache.dubbo.common.utils.HttpUtils.buildPath;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.CONTROLLER_ANNOTATION_CLASS_NAME;
|
||||
import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_MAPPING_ANNOTATION_CLASS_NAME;
|
||||
|
||||
/**
|
||||
* {@link ServiceRestMetadataResolver}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
|
||||
|
||||
private static final int FIRST_ELEMENT_INDEX = 0;
|
||||
|
||||
@Override
|
||||
protected boolean supports0(Class<?> serviceType) {
|
||||
return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
return isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
String requestBasePath = resolveRequestPath(serviceType);
|
||||
String requestRelativePath = resolveRequestPath(serviceMethod);
|
||||
return buildPath(requestBasePath, requestRelativePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
|
||||
Annotation requestMapping = getRequestMapping(serviceMethod);
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> produces) {
|
||||
addMediaTypes(serviceMethod, "produces", produces);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> consumes) {
|
||||
addMediaTypes(serviceMethod, "consumes", consumes);
|
||||
}
|
||||
|
||||
private String resolveRequestPath(AnnotatedElement annotatedElement) {
|
||||
Annotation mappingAnnotation = getRequestMapping(annotatedElement);
|
||||
// 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];
|
||||
}
|
||||
|
||||
private void addMediaTypes(Method serviceMethod, String annotationAttributeName, Set<String> mediaTypesSet) {
|
||||
|
||||
Annotation mappingAnnotation = getRequestMapping(serviceMethod);
|
||||
|
||||
String[] mediaTypes = getAttribute(mappingAnnotation, annotationAttributeName);
|
||||
|
||||
if (isNotEmpty(mediaTypes)) {
|
||||
of(mediaTypes).forEach(mediaTypesSet::add);
|
||||
}
|
||||
}
|
||||
|
||||
private Annotation getRequestMapping(AnnotatedElement annotatedElement) {
|
||||
// try "@RequestMapping" first
|
||||
Annotation requestMapping = findAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
|
||||
// try the annotation meta-annotated later
|
||||
if (requestMapping == null) {
|
||||
requestMapping = findMetaAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
|
||||
}
|
||||
return requestMapping;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# JAX-RS's implementations
|
||||
jax-rs.query-param = org.apache.dubbo.metadata.rest.jaxrs.QueryParamParameterProcessor
|
||||
jax-rs.form-param = org.apache.dubbo.metadata.rest.jaxrs.FormParamParameterProcessor
|
||||
jax-rs.matrix-param = org.apache.dubbo.metadata.rest.jaxrs.MatrixParamParameterProcessor
|
||||
jax-rs.header-param = org.apache.dubbo.metadata.rest.jaxrs.HeaderParamParameterProcessor
|
||||
jax-rs.default-value-param = org.apache.dubbo.metadata.rest.jaxrs.DefaultValueParameterProcessor
|
||||
|
||||
# Spring Web MVC's implementations
|
||||
spring-webmvc.request-param = org.apache.dubbo.metadata.rest.springmvc.RequestParamParameterProcessor
|
||||
spring-webmvc.request-header = org.apache.dubbo.metadata.rest.springmvc.RequestHeaderParameterProcessor
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
default =
|
||||
jax-rs = org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver
|
||||
spring-webmvc = org.apache.dubbo.metadata.rest.springmvc.SpringMvcServiceRestMetadataResolver
|
||||
|
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||
/**
|
||||
* 2018/11/6
|
||||
*/
|
||||
public class ServiceDefinitionBuildderTest {
|
||||
public class ServiceDefinitionBuilderTest {
|
||||
|
||||
@Test
|
||||
public void testBuilderComplextObject() {
|
||||
|
|
@ -77,7 +77,7 @@ public class ServiceDefinitionBuildderTest {
|
|||
}
|
||||
}
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String, java.lang.String>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), ComplexObject.InnerObject.class.getName());
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
|
||||
Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
|
||||
|
|
@ -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.rest;
|
||||
|
||||
import org.apache.dubbo.config.annotation.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link RestService}
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
@Service(version = "1.0.0")
|
||||
public class DefaultRestService implements RestService {
|
||||
|
||||
@Override
|
||||
public String param(String param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String params(int a, String b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String headers(String header, String header2, Integer param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pathVariables(String path1, String path2, String param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String form(String form) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User requestBodyMap(Map<String, Object> data, String param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> requestBodyUser(User user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public User user(User user) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An interface for REST service
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
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.6
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
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"}, group = "standard")
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.rest;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* User Entity
|
||||
*
|
||||
* @since 2.7.6
|
||||
*/
|
||||
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 + '}';
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue