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:
Mercy Ma 2020-02-17 20:15:43 +08:00 committed by GitHub
parent d30ca86395
commit 7b0ae127a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
192 changed files with 16107 additions and 85 deletions

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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> {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
/**

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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);
// }
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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

View File

@ -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

View File

@ -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());
}
}

View File

@ -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() {
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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");
});
}
}

View File

@ -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");
});
}
}

View File

@ -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");
});
}
}

View File

@ -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");
});
}
}

View File

@ -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");
});
}
}

View File

@ -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));
}
}

View File

@ -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");
});
}
}

View File

@ -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));
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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[]");

View File

@ -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;

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 + "}";
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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 + '}';
}
}

View File

@ -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";
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,3 @@
default =
jax-rs = org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver
spring-webmvc = org.apache.dubbo.metadata.rest.springmvc.SpringMvcServiceRestMetadataResolver

View File

@ -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[]");

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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