Revert "revert metadata related changes"

This reverts commit 50315fe3d1.
This commit is contained in:
ken.lj 2019-11-15 13:30:32 +08:00
parent 8d7e483bbd
commit a7a26d8977
149 changed files with 1648 additions and 9145 deletions

View File

@ -25,7 +25,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
/**
* The factory interface to create the instance of {@link DynamicConfiguration}
*/
@SPI("file") // 2.7.5 change the default SPI implementation
@SPI("nop")
public interface DynamicConfigurationFactory {
DynamicConfiguration getDynamicConfiguration(URL url);

View File

@ -19,7 +19,6 @@ 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;
@ -41,8 +40,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -51,17 +49,17 @@ 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;
/**
*
* {@link org.apache.dubbo.rpc.model.ApplicationModel}, {@code DubboBootstrap} and this class are
* at present designed to be singleton or static (by itself totally static or uses some static fields).
* So the instances returned from them are of process or classloader scope. If you want to support
* multiple dubbo servers in a single process, you may need to refactor these three classes.
* <p>
*
* Load dubbo extensions
* <ul>
* <li>auto inject dependency extension </li>
@ -406,7 +404,7 @@ public class ExtensionLoader<T> {
* @return non-null
*/
public T getOrDefaultExtension(String name) {
return containsExtension(name) ? getExtension(name) : getDefaultExtension();
return containsExtension(name) ? getExtension(name) : getDefaultExtension();
}
/**
@ -434,16 +432,14 @@ public class ExtensionLoader<T> {
}
public Set<T> getSupportedExtensionInstances() {
List<T> instances = new LinkedList<>();
Set<T> instances = new HashSet<>();
Set<String> supportedExtensions = getSupportedExtensions();
if (CollectionUtils.isNotEmpty(supportedExtensions)) {
for (String name : supportedExtensions) {
instances.add(getExtension(name));
}
}
// sort the Prioritized instances
sort(instances, Prioritized.COMPARATOR);
return new LinkedHashSet<>(instances);
return instances;
}
/**
@ -716,7 +712,7 @@ public class ExtensionLoader<T> {
/**
* synchronized in getExtensionClasses
*/
* */
private Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName();
@ -763,7 +759,7 @@ public class ExtensionLoader<T> {
try {
Enumeration<java.net.URL> urls = null;
ClassLoader classLoader = findClassLoader();
// try to load from ExtensionLoader's ClassLoader first
if (extensionLoaderClassLoaderFirst) {
ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
@ -771,8 +767,8 @@ public class ExtensionLoader<T> {
urls = extensionLoaderClassLoader.getResources(fileName);
}
}
if (urls == null || !urls.hasMoreElements()) {
if(urls == null || !urls.hasMoreElements()) {
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {

View File

@ -1,74 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.function;
import java.util.function.Predicate;
import static java.util.stream.Stream.of;
/**
* The utilities class for Java {@link Predicate}
*
* @since 2.7.5
*/
public interface Predicates {
Predicate[] EMPTY_ARRAY = new Predicate[0];
/**
* {@link Predicate} always return <code>true</code>
*
* @param <T> the type to test
* @return <code>true</code>
*/
static <T> Predicate<T> alwaysTrue() {
return e -> true;
}
/**
* {@link Predicate} always return <code>false</code>
*
* @param <T> the type to test
* @return <code>false</code>
*/
static <T> Predicate<T> alwaysFalse() {
return e -> false;
}
/**
* a composed predicate that represents a short-circuiting logical AND of {@link Predicate predicates}
*
* @param predicates {@link Predicate predicates}
* @param <T> the type to test
* @return non-null
*/
static <T> Predicate<T> and(Predicate<T>... predicates) {
return of(predicates).reduce((a, b) -> a.and(b)).orElseGet(Predicates::alwaysTrue);
}
/**
* a composed predicate that represents a short-circuiting logical OR of {@link Predicate predicates}
*
* @param predicates {@link Predicate predicates}
* @param <T> the detected type
* @return non-null
*/
static <T> Predicate<T> or(Predicate<T>... predicates) {
return of(predicates).reduce((a, b) -> a.or(b)).orElse(e -> true);
}
}

View File

@ -1,71 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.function;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
import static java.util.stream.StreamSupport.stream;
import static org.apache.dubbo.common.function.Predicates.and;
import static org.apache.dubbo.common.function.Predicates.or;
/**
* The utilities class for {@link Stream}
*
* @since 2.7.5
*/
public interface Streams {
static <T, S extends Iterable<T>> Stream<T> filterStream(S values, Predicate<T> predicate) {
return stream(values.spliterator(), false).filter(predicate);
}
static <T, S extends Iterable<T>> List<T> filterList(S values, Predicate<T> predicate) {
return filterStream(values, predicate).collect(toList());
}
static <T, S extends Iterable<T>> Set<T> filterSet(S values, Predicate<T> predicate) {
// new Set with insertion order
return filterStream(values, predicate).collect(LinkedHashSet::new, Set::add, Set::addAll);
}
static <T, S extends Iterable<T>> S filter(S values, Predicate<T> predicate) {
final boolean isSet = Set.class.isAssignableFrom(values.getClass());
return (S) (isSet ? filterSet(values, predicate) : filterList(values, predicate));
}
static <T, S extends Iterable<T>> S filterAll(S values, Predicate<T>... predicates) {
return filter(values, and(predicates));
}
static <T, S extends Iterable<T>> S filterAny(S values, Predicate<T>... predicates) {
return filter(values, or(predicates));
}
static <T> T filterFirst(Iterable<T> values, Predicate<T>... predicates) {
return stream(values.spliterator(), false)
.filter(and(predicates))
.findFirst()
.orElse(null);
}
}

View File

@ -21,14 +21,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableSet;
public class CollectionUtils {
@ -179,7 +173,7 @@ public class CollectionUtils {
public static Map<String, String> toStringMap(String... pairs) {
Map<String, String> parameters = new HashMap<>();
if (ArrayUtils.isEmpty(pairs)) {
if(ArrayUtils.isEmpty(pairs)){
return parameters;
}
@ -227,17 +221,4 @@ public class CollectionUtils {
return !isEmptyMap(map);
}
/**
* Convert to multiple values to be {@link LinkedHashSet}
*
* @param values one or more values
* @param <T> the type of <code>values</code>
* @return read-only {@link Set}
*/
public static <T> Set<T> ofSet(T... values) {
if (values == null || values.length < 1) {
return emptySet();
}
return unmodifiableSet(new LinkedHashSet<>(asList(values)));
}
}

View File

@ -33,7 +33,6 @@ import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.valueOf;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX;
@ -59,34 +58,6 @@ public final class StringUtils {
private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$");
private static final int PAD_LIMIT = 8192;
/**
* @since 2.7.5
*/
public static final char EQUAL_CHAR = '=';
public static final String EQUAL = valueOf(EQUAL_CHAR);
public static final char AND_CHAR = '&';
public static final String AND = valueOf(AND_CHAR);
public static final char SEMICOLON_CHAR = ';';
public static final String SEMICOLON = valueOf(SEMICOLON_CHAR);
public static final char QUESTION_MASK_CHAR = '?';
public static final String QUESTION_MASK = valueOf(QUESTION_MASK_CHAR);
public static final char SLASH_CHAR = '/';
public static final String SLASH = valueOf(SLASH_CHAR);
/**
* The empty value
*/
public static final String EMPTY_VALUE = "";
private StringUtils() {
}

View File

@ -62,10 +62,8 @@ import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
public static final String NAME = "config";
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
private final Map<String, Map<String, AbstractConfig>> configsCache = newMap();

View File

@ -1,60 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.function;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.function.Predicates.alwaysFalse;
import static org.apache.dubbo.common.function.Predicates.alwaysTrue;
import static org.apache.dubbo.common.function.Predicates.and;
import static org.apache.dubbo.common.function.Predicates.or;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link Predicates} Test
*
* @since 2.7.5
*/
public class PredicatesTest {
@Test
public void testAlwaysTrue() {
assertTrue(alwaysTrue().test(null));
}
@Test
public void testAlwaysFalse() {
assertFalse(alwaysFalse().test(null));
}
@Test
public void testAnd() {
assertTrue(and(alwaysTrue(), alwaysTrue(), alwaysTrue()).test(null));
assertFalse(and(alwaysFalse(), alwaysFalse(), alwaysFalse()).test(null));
assertFalse(and(alwaysTrue(), alwaysFalse(), alwaysFalse()).test(null));
assertFalse(and(alwaysTrue(), alwaysTrue(), alwaysFalse()).test(null));
}
@Test
public void testOr() {
assertTrue(or(alwaysTrue(), alwaysTrue(), alwaysTrue()).test(null));
assertTrue(or(alwaysTrue(), alwaysTrue(), alwaysFalse()).test(null));
assertTrue(or(alwaysTrue(), alwaysFalse(), alwaysFalse()).test(null));
assertFalse(or(alwaysFalse(), alwaysFalse(), alwaysFalse()).test(null));
}
}

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.function;
import org.junit.jupiter.api.Test;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.apache.dubbo.common.function.Streams.filterList;
import static org.apache.dubbo.common.function.Streams.filterSet;
import static org.apache.dubbo.common.function.Streams.filterStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link Streams} Test
*
* @since 2.7.5
*/
public class StreamsTest {
@Test
public void testFilterStream() {
Stream<Integer> stream = filterStream(asList(1, 2, 3, 4, 5), i -> i % 2 == 0);
assertEquals(asList(2, 4), stream.collect(toList()));
}
@Test
public void testFilterList() {
List<Integer> list = filterList(asList(1, 2, 3, 4, 5), i -> i % 2 == 0);
assertEquals(asList(2, 4), list);
}
@Test
public void testFilterSet() {
Set<Integer> set = filterSet(asList(1, 2, 3, 4, 5), i -> i % 2 == 0);
assertEquals(new LinkedHashSet<>(asList(2, 4)), set);
}
}

View File

@ -24,25 +24,21 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
import static org.apache.dubbo.common.utils.CollectionUtils.toMap;
import static org.apache.dubbo.common.utils.CollectionUtils.toStringMap;
import static org.hamcrest.MatcherAssert.assertThat;
import static java.util.Collections.emptyList;
import static java.util.Collections.singleton;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
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.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class CollectionUtilsTest {
@ -199,20 +195,4 @@ public class CollectionUtilsTest {
public void testIsNotEmpty() throws Exception {
assertThat(isNotEmpty(singleton("a")), is(true));
}
@Test
public void testOfSet() {
Set<String> set = ofSet();
assertEquals(emptySet(), set);
set = ofSet(((String[]) null));
assertEquals(emptySet(), set);
set = ofSet("A", "B", "C");
Set<String> expectedSet = new LinkedHashSet<>();
expectedSet.add("A");
expectedSet.add("B");
expectedSet.add("C");
assertEquals(expectedSet, set);
}
}

View File

@ -1,223 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.context;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.rpc.model.ApplicationModel.getConfigManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link ConfigManager} Test
*
* @since 2.7.5
*/
public class ConfigManagerTest {
private ConfigManager configManager = getConfigManager();
@BeforeEach
public void init() {
configManager.clear();
}
@Test
public void testDefaultValues() {
// assert single
assertFalse(configManager.getApplication().isPresent());
assertFalse(configManager.getMonitor().isPresent());
assertFalse(configManager.getModule().isPresent());
assertFalse(configManager.getMetrics().isPresent());
// providers and consumers
assertFalse(configManager.getDefaultProvider().isPresent());
assertFalse(configManager.getDefaultConsumer().isPresent());
assertTrue(configManager.getProviders().isEmpty());
assertTrue(configManager.getConsumers().isEmpty());
// protocols
assertTrue(configManager.getProtocols().isEmpty());
assertTrue(configManager.getDefaultProtocols().isEmpty());
assertTrue(configManager.getProtocolIds().isEmpty());
// registries
assertTrue(configManager.getRegistries().isEmpty());
assertTrue(configManager.getDefaultRegistries().isEmpty());
assertTrue(configManager.getRegistryIds().isEmpty());
// services and references
assertTrue(configManager.getServices().isEmpty());
assertTrue(configManager.getReferences().isEmpty());
// config centers
assertTrue(configManager.getConfigCenters().isEmpty());
// metadata
assertTrue(configManager.getMetadataConfigs().isEmpty());
}
// Test ApplicationConfig correlative methods
@Test
public void testApplicationConfig() {
ApplicationConfig config = new ApplicationConfig();
configManager.setApplication(config);
assertTrue(configManager.getApplication().isPresent());
assertEquals(config, configManager.getApplication().get());
assertThrows(IllegalStateException.class, () -> {
configManager.setApplication(new ApplicationConfig("test"));
});
}
// Test MonitorConfig correlative methods
@Test
public void testMonitorConfig() {
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setGroup("test");
configManager.setMonitor(monitorConfig);
assertTrue(configManager.getMonitor().isPresent());
assertEquals(monitorConfig, configManager.getMonitor().get());
assertThrows(IllegalStateException.class, () -> {
configManager.setMonitor(new MonitorConfig());
});
}
// Test MonitorConfig correlative methods
@Test
public void tesModuleConfig() {
ModuleConfig config = new ModuleConfig();
configManager.setModule(config);
assertTrue(configManager.getModule().isPresent());
assertEquals(config, configManager.getModule().get());
assertThrows(IllegalStateException.class, () -> {
configManager.setModule(new ModuleConfig("test"));
});
}
// Test MetricsConfig correlative methods
@Test
public void tesMetricsConfig() {
MetricsConfig config = new MetricsConfig();
configManager.setMetrics(config);
assertTrue(configManager.getMetrics().isPresent());
assertEquals(config, configManager.getMetrics().get());
assertThrows(IllegalStateException.class, () -> {
MetricsConfig metricsConfig = new MetricsConfig();
metricsConfig.setPort("101");
configManager.setMetrics(metricsConfig);
});
}
// Test ProviderConfig correlative methods
@Test
public void testProviderConfig() {
ProviderConfig config = new ProviderConfig();
configManager.addProviders(asList(config, null));
Collection<ProviderConfig> configs = configManager.getProviders();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
assertFalse(configManager.getDefaultProvider().isPresent());
config.setId(DEFAULT_KEY);
configManager.addProvider(config);
assertTrue(configManager.getDefaultProvider().isPresent());
configs = configManager.getProviders();
assertEquals(2, configs.size());
}
// Test ConsumerConfig correlative methods
@Test
public void testConsumerConfig() {
ConsumerConfig config = new ConsumerConfig();
configManager.addConsumers(asList(config, null));
Collection<ConsumerConfig> configs = configManager.getConsumers();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
assertFalse(configManager.getDefaultConsumer().isPresent());
config.setId(DEFAULT_KEY);
configManager.addConsumer(config);
assertTrue(configManager.getDefaultConsumer().isPresent());
configs = configManager.getConsumers();
assertEquals(2, configs.size());
}
// Test ProtocolConfig correlative methods
@Test
public void testProtocolConfig() {
ProtocolConfig config = new ProtocolConfig();
configManager.addProtocols(asList(config, null));
Collection<ProtocolConfig> configs = configManager.getProtocols();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
assertFalse(configManager.getDefaultProtocols().isEmpty());
}
// Test RegistryConfig correlative methods
@Test
public void testRegistryConfig() {
RegistryConfig config = new RegistryConfig();
configManager.addRegistries(asList(config, null));
Collection<RegistryConfig> configs = configManager.getRegistries();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
assertFalse(configManager.getDefaultRegistries().isEmpty());
}
// Test ConfigCenterConfig correlative methods
@Test
public void testConfigCenterConfig() {
ConfigCenterConfig config = new ConfigCenterConfig();
configManager.addConfigCenters(asList(config, null));
Collection<ConfigCenterConfig> configs = configManager.getConfigCenters();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
}
@Test
public void testAddConfig() {
configManager.addConfig(new ApplicationConfig());
configManager.addConfig(new ProviderConfig());
configManager.addConfig(new ProtocolConfig());
assertTrue(configManager.getApplication().isPresent());
assertFalse(configManager.getProviders().isEmpty());
assertFalse(configManager.getProtocols().isEmpty());
}
@Test
public void testRefreshAll() {
configManager.refreshAll();
}
}

View File

@ -67,124 +67,29 @@
</dependency>
<!-- FIXME, we shouldn't rely on these modules, even in test scope -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rmi</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-hessian</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-netty4</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-multicast</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-eureka</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-etcd3</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-consul</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-etcd</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-redis</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-configcenter-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -36,7 +36,7 @@ public class NacosDubboServiceConsumerBootstrap {
// Zookeeper
// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=service-provider"))
.metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();

View File

@ -32,17 +32,18 @@ public class ZookeeperDubboServiceConsumerBootstrap {
.registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=zookeeper-dubbo-provider"))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
.start()
.await();
EchoService echoService = bootstrap.getCache().get(EchoService.class);
UserService userService = bootstrap.getCache().get(UserService.class);
for (int i = 0; i < 5; i++) {
for (int i = 0; i < 500; i++) {
Thread.sleep(2000L);
System.out.println(echoService.echo("Hello,World"));
System.out.println(userService.getUser(i * 1L));
}
bootstrap.stop();
}
}

View File

@ -56,12 +56,6 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-default</artifactId>

View File

@ -30,8 +30,8 @@ import org.springframework.util.Assert;
import java.lang.annotation.Annotation;
import java.util.List;
import static com.alibaba.spring.util.BeanFactoryUtils.getBeans;
import static com.alibaba.spring.util.BeanFactoryUtils.getOptionalBean;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getBeans;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getNullableBean;
/**
* Abstract Configurable {@link Annotation} Bean Builder
@ -132,7 +132,7 @@ abstract class AbstractAnnotationConfigBeanBuilder<A extends Annotation, B exten
String monitorBeanName = resolveMonitorConfigBeanName(annotation);
MonitorConfig monitorConfig = getOptionalBean(applicationContext, monitorBeanName, MonitorConfig.class);
MonitorConfig monitorConfig = getNullableBean(applicationContext, monitorBeanName, MonitorConfig.class);
bean.setMonitor(monitorConfig);
@ -143,7 +143,7 @@ abstract class AbstractAnnotationConfigBeanBuilder<A extends Annotation, B exten
String applicationConfigBeanName = resolveApplicationConfigBeanName(annotation);
ApplicationConfig applicationConfig =
getOptionalBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
getNullableBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
bean.setApplication(applicationConfig);
@ -154,7 +154,7 @@ abstract class AbstractAnnotationConfigBeanBuilder<A extends Annotation, B exten
String moduleConfigBeanName = resolveModuleConfigBeanName(annotation);
ModuleConfig moduleConfig =
getOptionalBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
getNullableBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
bean.setModule(moduleConfig);

View File

@ -31,8 +31,8 @@ import org.springframework.util.Assert;
import java.lang.annotation.Annotation;
import java.util.List;
import static com.alibaba.spring.util.BeanFactoryUtils.getBeans;
import static com.alibaba.spring.util.BeanFactoryUtils.getOptionalBean;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getBeans;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getNullableBean;
/**
* An Abstract Builder to build {@link AbstractInterfaceConfig Interface Config} Bean that annotated
@ -133,7 +133,7 @@ public abstract class AnnotatedInterfaceConfigBeanBuilder<C extends AbstractInte
String monitorBeanName = resolveMonitorConfigBeanName(attributes);
MonitorConfig monitorConfig = getOptionalBean(applicationContext, monitorBeanName, MonitorConfig.class);
MonitorConfig monitorConfig = getNullableBean(applicationContext, monitorBeanName, MonitorConfig.class);
configBean.setMonitor(monitorConfig);
@ -144,7 +144,7 @@ public abstract class AnnotatedInterfaceConfigBeanBuilder<C extends AbstractInte
String applicationConfigBeanName = resolveApplicationConfigBeanName(attributes);
ApplicationConfig applicationConfig =
getOptionalBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
getNullableBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
configBean.setApplication(applicationConfig);
@ -155,7 +155,7 @@ public abstract class AnnotatedInterfaceConfigBeanBuilder<C extends AbstractInte
String moduleConfigBeanName = resolveModuleConfigBeanName(attributes);
ModuleConfig moduleConfig =
getOptionalBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
getNullableBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
configBean.setModule(moduleConfig);

View File

@ -0,0 +1,548 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getMergedAttributes;
import static org.springframework.core.BridgeMethodResolver.findBridgedMethod;
import static org.springframework.core.BridgeMethodResolver.isVisibilityBridgeMethodPair;
/**
* Abstract generic {@link BeanPostProcessor} implementation for customized annotation that annotated injected-object.
* <p>
*
* @revision 2.7.3 Uses {@link AnnotationAttributes} instead of {@link Annotation}
* @since 2.6.6
*/
public abstract class AnnotationInjectedBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
private final static int CACHE_SIZE = Integer.getInteger("", 32);
private final Log logger = LogFactory.getLog(getClass());
private final Class<? extends Annotation>[] annotationTypes;
private final ConcurrentMap<String, AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata> injectionMetadataCache =
new ConcurrentHashMap<String, AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata>(CACHE_SIZE);
private final ConcurrentMap<String, Object> injectedObjectsCache = new ConcurrentHashMap<>(CACHE_SIZE);
private ConfigurableListableBeanFactory beanFactory;
private Environment environment;
private ClassLoader classLoader;
/**
* make sure higher priority than {@link AutowiredAnnotationBeanPostProcessor}
*
* @revision 2.7.3
*/
private int order = Ordered.LOWEST_PRECEDENCE - 3;
/**
* @param annotationTypes the multiple types of {@link Annotation annotations}
* @since 2.7.3
*/
public AnnotationInjectedBeanPostProcessor(Class<? extends Annotation>... annotationTypes) {
Assert.notEmpty(annotationTypes, "The argument of annotations' types must not empty");
this.annotationTypes = annotationTypes;
}
@SafeVarargs
private static <T> Collection<T> combine(Collection<? extends T>... elements) {
List<T> allElements = new ArrayList<>();
for (Collection<? extends T> e : elements) {
allElements.addAll(e);
}
return allElements;
}
/**
* Annotation type
*
* @return non-null
* @deprecated 2.7.3, uses {@link #getAnnotationTypes()}
*/
@Deprecated
public final Class<? extends Annotation> getAnnotationType() {
return annotationTypes[0];
}
protected final Class<? extends Annotation>[] getAnnotationTypes() {
return annotationTypes;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory,
"AnnotationInjectedBeanPostProcessor requires a ConfigurableListableBeanFactory");
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
+ " dependencies is failed", ex);
}
return pvs;
}
/**
* Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated fields
*
* @param beanClass The {@link Class} of Bean
* @return non-null {@link List}
*/
private List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> findFieldAnnotationMetadata(final Class<?> beanClass) {
final List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>();
ReflectionUtils.doWithFields(beanClass, field -> {
for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
AnnotationAttributes attributes = getMergedAttributes(field, annotationType, getEnvironment(), true);
if (attributes != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("@" + annotationType.getName() + " is not supported on static fields: " + field);
}
return;
}
elements.add(new AnnotatedFieldElement(field, attributes));
}
}
});
return elements;
}
/**
* Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated methods
*
* @param beanClass The {@link Class} of Bean
* @return non-null {@link List}
*/
private List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> findAnnotatedMethodMetadata(final Class<?> beanClass) {
final List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>();
ReflectionUtils.doWithMethods(beanClass, method -> {
Method bridgedMethod = findBridgedMethod(method);
if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
AnnotationAttributes attributes = getMergedAttributes(bridgedMethod, annotationType, getEnvironment(), true);
if (attributes != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("@" + annotationType.getName() + " annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterTypes().length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("@" + annotationType.getName() + " annotation should only be used on methods with parameters: " +
method);
}
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
elements.add(new AnnotatedMethodElement(method, pd, attributes));
}
}
});
return elements;
}
private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
return new AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
}
private InjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
try {
metadata = buildAnnotatedMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
} catch (NoClassDefFoundError err) {
throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
"] for annotation metadata: could not find class that it depends on", err);
}
}
}
}
return metadata;
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanType != null) {
InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
@Override
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public void destroy() throws Exception {
for (Object object : injectedObjectsCache.values()) {
if (logger.isInfoEnabled()) {
logger.info(object + " was destroying!");
}
if (object instanceof DisposableBean) {
((DisposableBean) object).destroy();
}
}
injectionMetadataCache.clear();
injectedObjectsCache.clear();
if (logger.isInfoEnabled()) {
logger.info(getClass() + " was destroying!");
}
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
protected Environment getEnvironment() {
return environment;
}
protected ClassLoader getClassLoader() {
return classLoader;
}
protected ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
/**
* Gets all injected-objects.
*
* @return non-null {@link Collection}
*/
protected Collection<Object> getInjectedObjects() {
return this.injectedObjectsCache.values();
}
/**
* Get injected-object from specified {@link AnnotationAttributes annotation attributes} and Bean Class
*
* @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
* @param injectedElement {@link InjectionMetadata.InjectedElement}
* @return An injected object
* @throws Exception If getting is failed
*/
protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
Object injectedObject = injectedObjectsCache.get(cacheKey);
if (injectedObject == null) {
injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
// Customized inject-object if necessary
injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
}
return injectedObject;
}
/**
* Subclass must implement this method to get injected-object. The context objects could help this method if
* necessary :
* <ul>
* <li>{@link #getBeanFactory() BeanFactory}</li>
* <li>{@link #getClassLoader() ClassLoader}</li>
* <li>{@link #getEnvironment() Environment}</li>
* </ul>
*
* @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
* @param injectedElement {@link InjectionMetadata.InjectedElement}
* @return The injected object
* @throws Exception If resolving an injected object is failed.
*/
protected abstract Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception;
/**
* Build a cache key for injected-object. The context objects could help this method if
* necessary :
* <ul>
* <li>{@link #getBeanFactory() BeanFactory}</li>
* <li>{@link #getClassLoader() ClassLoader}</li>
* <li>{@link #getEnvironment() Environment}</li>
* </ul>
*
* @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
* @param injectedElement {@link InjectionMetadata.InjectedElement}
* @return Bean cache key
*/
protected abstract String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName,
Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement);
/**
* Get {@link Map} in injected field.
*
* @return non-null ready-only {@link Map}
*/
protected Map<InjectionMetadata.InjectedElement, Object> getInjectedFieldObjectsMap() {
Map<InjectionMetadata.InjectedElement, Object> injectedElementBeanMap =
new LinkedHashMap<InjectionMetadata.InjectedElement, Object>();
for (AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) {
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements = metadata.getFieldElements();
for (AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement fieldElement : fieldElements) {
injectedElementBeanMap.put(fieldElement, fieldElement.bean);
}
}
return Collections.unmodifiableMap(injectedElementBeanMap);
}
/**
* Get {@link Map} in injected method.
*
* @return non-null {@link Map}
*/
protected Map<InjectionMetadata.InjectedElement, Object> getInjectedMethodObjectsMap() {
Map<InjectionMetadata.InjectedElement, Object> injectedElementBeanMap =
new LinkedHashMap<InjectionMetadata.InjectedElement, Object>();
for (AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) {
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements = metadata.getMethodElements();
for (AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement methodElement : methodElements) {
injectedElementBeanMap.put(methodElement, methodElement.object);
}
}
return Collections.unmodifiableMap(injectedElementBeanMap);
}
/**
* {@link Annotation Annotated} {@link InjectionMetadata} implementation
*/
private class AnnotatedInjectionMetadata extends InjectionMetadata {
private final Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements;
private final Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements;
public AnnotatedInjectionMetadata(Class<?> targetClass, Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements,
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements) {
super(targetClass, combine(fieldElements, methodElements));
this.fieldElements = fieldElements;
this.methodElements = methodElements;
}
public Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> getFieldElements() {
return fieldElements;
}
public Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> getMethodElements() {
return methodElements;
}
}
/**
* {@link Annotation Annotated} {@link Method} {@link InjectionMetadata.InjectedElement}
*/
private class AnnotatedMethodElement extends InjectionMetadata.InjectedElement {
private final Method method;
private final AnnotationAttributes attributes;
private volatile Object object;
protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, AnnotationAttributes attributes) {
super(method, pd);
this.method = method;
this.attributes = attributes;
}
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Class<?> injectedType = pd.getPropertyType();
Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(method);
method.invoke(bean, injectedObject);
}
}
/**
* {@link Annotation Annotated} {@link Field} {@link InjectionMetadata.InjectedElement}
*/
public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {
private final Field field;
private final AnnotationAttributes attributes;
private volatile Object bean;
protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) {
super(field, null);
this.field = field;
this.attributes = attributes;
}
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Class<?> injectedType = field.getType();
Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(field);
field.set(bean, injectedObject);
}
}
}

View File

@ -24,7 +24,8 @@ import org.springframework.core.env.PropertyResolver;
import java.lang.annotation.Annotation;
import java.util.Map;
import static com.alibaba.spring.util.AnnotationUtils.getAttributes;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolvePlaceholders;
/**
* {@link Annotation} {@link PropertyValues} Adapter
@ -45,7 +46,7 @@ class AnnotationPropertyValuesAdapter implements PropertyValues {
*/
public AnnotationPropertyValuesAdapter(Map<String, Object> attributes, PropertyResolver propertyResolver,
String... ignoreAttributeNames) {
this.delegate = new MutablePropertyValues(getAttributes(attributes, propertyResolver, ignoreAttributeNames));
this.delegate = new MutablePropertyValues(resolvePlaceholders(attributes, propertyResolver, ignoreAttributeNames));
}
public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver,

View File

@ -25,7 +25,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import static com.alibaba.spring.util.BeanRegistrar.hasAlias;
import static org.apache.dubbo.config.spring.util.BeanRegistrar.hasAlias;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import static org.springframework.util.StringUtils.hasText;

View File

@ -21,8 +21,8 @@ import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.apache.dubbo.config.spring.util.AnnotationUtils;
import com.alibaba.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@ -44,10 +44,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static com.alibaba.spring.util.AnnotationUtils.getAttributes;
import static java.lang.reflect.Proxy.newProxyInstance;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
import static org.springframework.util.StringUtils.hasText;
/**
@ -56,7 +55,7 @@ import static org.springframework.util.StringUtils.hasText;
*
* @since 2.5.7
*/
public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements
public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor implements
ApplicationContextAware, ApplicationListener {
/**
@ -300,7 +299,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement) {
return buildReferencedBeanName(attributes, injectedType) +
"#source=" + (injectedElement.getMember()) +
"#attributes=" + getAttributes(attributes, getEnvironment());
"#attributes=" + AnnotationUtils.resolvePlaceholders(attributes, getEnvironment());
}
/**

View File

@ -34,11 +34,11 @@ import java.beans.PropertyEditorSupport;
import java.util.List;
import java.util.Map;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static com.alibaba.spring.util.AnnotationUtils.getAttributes;
import static com.alibaba.spring.util.BeanFactoryUtils.getOptionalBean;
import static com.alibaba.spring.util.ObjectUtils.of;
import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveServiceInterfaceClass;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveServiceInterfaceClass;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getNullableBean;
import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
@ -81,7 +81,7 @@ class ReferenceBeanBuilder extends AnnotatedInterfaceConfigBeanBuilder<Reference
String consumerBeanName = getAttribute(attributes, "consumer");
ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);
ConsumerConfig consumerConfig = getNullableBean(applicationContext, consumerBeanName, ConsumerConfig.class);
referenceBean.setConsumer(consumerConfig);

View File

@ -63,9 +63,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.alibaba.spring.util.ObjectUtils.of;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveServiceInterfaceClass;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveServiceInterfaceClass;
import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR;
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;

View File

@ -25,8 +25,8 @@ import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveInterfaceName;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
/**

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring.context.annotation;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.util.BeanRegistrar;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@ -36,7 +37,6 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
/**
@ -87,7 +87,7 @@ public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistra
private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
// Register @Reference Annotation Bean Processor
registerInfrastructureBean(registry,
BeanRegistrar.registerInfrastructureBean(registry,
ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
}

View File

@ -21,7 +21,6 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigBindin
import org.apache.dubbo.config.spring.beans.factory.config.ConfigurableSourceBeanMetadataElement;
import org.apache.dubbo.config.spring.context.config.NamePropertyDefaultValueDubboConfigBeanCustomizer;
import com.alibaba.spring.beans.factory.annotation.ConfigurationBeanBindingRegistrar;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@ -44,13 +43,12 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
import static com.alibaba.spring.util.PropertySourcesUtils.normalizePrefix;
import static org.apache.dubbo.config.spring.context.config.NamePropertyDefaultValueDubboConfigBeanCustomizer.BEAN_NAME;
import static org.apache.dubbo.config.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.apache.dubbo.config.spring.util.PropertySourcesUtils.buildPrefix;
import static org.apache.dubbo.config.spring.util.PropertySourcesUtils.getPrefixedProperties;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
/**
* {@link AbstractConfig Dubbo Config} binding Bean registrar
@ -58,9 +56,7 @@ import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
* @see EnableDubboConfigBinding
* @see DubboConfigBindingBeanPostProcessor
* @since 2.5.8
* @deprecated it will be removed in future, please use {@link ConfigurationBeanBindingRegistrar} for replacement
*/
@Deprecated
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware,
ConfigurableSourceBeanMetadataElement {
@ -71,7 +67,8 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName()));
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName()));
registerBeanDefinitions(attributes, registry);
@ -94,7 +91,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra
boolean multiple,
BeanDefinitionRegistry registry) {
Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix);
Map<String, Object> properties = getPrefixedProperties(environment.getPropertySources(), prefix);
if (CollectionUtils.isEmpty(properties)) {
if (log.isDebugEnabled()) {
@ -147,7 +144,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra
BeanDefinitionBuilder builder = rootBeanDefinition(processorClass);
String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix;
String actualPrefix = multiple ? buildPrefix(prefix) + beanName : prefix;
builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring.context.annotation;
import org.apache.dubbo.config.AbstractConfig;
import com.alibaba.spring.beans.factory.annotation.ConfigurationBeanBindingsRegister;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
@ -34,9 +33,7 @@ import org.springframework.util.Assert;
* @see EnableDubboConfigBindings
* @see DubboConfigBindingRegistrar
* @since 2.5.8
* @deprecated it will be removed in future, please use {@link ConfigurationBeanBindingsRegister} for replacement
*/
@Deprecated
public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private ConfigurableEnvironment environment;

View File

@ -28,17 +28,14 @@ import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.ConfigCenterBean;
import com.alibaba.spring.beans.factory.annotation.EnableConfigurationBeanBinding;
import com.alibaba.spring.beans.factory.annotation.EnableConfigurationBeanBindings;
import org.springframework.context.annotation.Configuration;
/**
* Dubbo {@link AbstractConfig Config} {@link Configuration}
*
* @revised 2.7.5
* @see Configuration
* @see EnableConfigurationBeanBindings
* @see EnableConfigurationBeanBinding
* @see EnableDubboConfigBindings
* @see EnableDubboConfigBinding
* @see ApplicationConfig
* @see ModuleConfig
* @see RegistryConfig
@ -54,17 +51,17 @@ public class DubboConfigConfiguration {
/**
* Single Dubbo {@link AbstractConfig Config} Bean Binding
*/
@EnableConfigurationBeanBindings({
@EnableConfigurationBeanBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.module", type = ModuleConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.metrics", type = MetricsConfig.class)
@EnableDubboConfigBindings({
@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
@EnableDubboConfigBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.metrics", type = MetricsConfig.class)
})
public static class Single {
@ -73,17 +70,17 @@ public class DubboConfigConfiguration {
/**
* Multiple Dubbo {@link AbstractConfig Config} Bean Binding
*/
@EnableConfigurationBeanBindings({
@EnableConfigurationBeanBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
@EnableDubboConfigBindings({
@EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
})
public static class Multiple {

View File

@ -25,8 +25,8 @@ import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import static com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
import static org.apache.dubbo.config.spring.util.BeanRegistrar.registerInfrastructureBean;
/**
* Dubbo {@link AbstractConfig Config} {@link ImportBeanDefinitionRegistrar register}, which order can be configured

View File

@ -23,7 +23,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import static com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
/**
* A {@link ImportBeanDefinitionRegistrar register} for the {@link Lifecycle Dubbo Lifecycle} components

View File

@ -22,7 +22,6 @@ import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor;
import com.alibaba.spring.beans.factory.annotation.EnableConfigurationBeanBinding;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.PropertySources;
@ -45,16 +44,13 @@ import java.lang.annotation.Target;
* @see DubboConfigBindingRegistrar
* @see DubboConfigBindingBeanPostProcessor
* @see EnableDubboConfigBindings
* @see EnableConfigurationBeanBinding
* @since 2.5.8
* @deprecated it will be removed in future, please use {@link EnableConfigurationBeanBinding} for replacement
*/
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(EnableDubboConfigBindings.class)
@Import(DubboConfigBindingRegistrar.class)
@Deprecated
public @interface EnableDubboConfigBinding {
/**

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.config.spring.context.annotation;
import com.alibaba.spring.beans.factory.annotation.EnableConfigurationBeanBindings;
import org.springframework.context.annotation.Import;
import java.lang.annotation.Annotation;
@ -29,15 +28,13 @@ import java.lang.annotation.Target;
/**
* Multiple {@link EnableDubboConfigBinding} {@link Annotation}
*
* @see EnableDubboConfigBinding
* @since 2.5.8
* @deprecated it will be removed in future, please use {@link EnableConfigurationBeanBindings} for replacement
* @see EnableDubboConfigBinding
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboConfigBindingsRegistrar.class)
@Deprecated
public @interface EnableDubboConfigBindings {
/**

View File

@ -24,7 +24,7 @@ import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import static com.alibaba.spring.util.ObjectUtils.of;
import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
import static org.springframework.beans.BeanUtils.getPropertyDescriptor;
/**

View File

@ -23,7 +23,7 @@ import org.springframework.validation.DataBinder;
import java.util.Map;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
import static org.apache.dubbo.config.spring.util.PropertySourcesUtils.getPrefixedProperties;
/**
* Default {@link DubboConfigBinder} implementation based on Spring {@link DataBinder}
@ -37,7 +37,7 @@ public class DefaultDubboConfigBinder extends AbstractDubboConfigBinder {
dataBinder.setIgnoreInvalidFields(isIgnoreInvalidFields());
dataBinder.setIgnoreUnknownFields(isIgnoreUnknownFields());
// Get properties under specified prefix from PropertySources
Map<String, Object> properties = getSubProperties(getPropertySources(), prefix);
Map<String, Object> properties = getPrefixedProperties(getPropertySources(), prefix);
// Convert Map to MutablePropertyValues
MutablePropertyValues propertyValues = new MutablePropertyValues(properties);
// Bind

View File

@ -22,7 +22,7 @@ import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.config.DubboShutdownHook;
import org.apache.dubbo.config.spring.util.ApplicationContextUtils;
import org.apache.dubbo.config.spring.util.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
@ -49,7 +49,7 @@ public class SpringExtensionFactory implements ExtensionFactory {
((ConfigurableApplicationContext) context).registerShutdownHook();
DubboShutdownHook.getDubboShutdownHook().unregister();
}
ApplicationContextUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
}
public static void removeApplicationContext(ApplicationContext context) {

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.config.spring.schema;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.util.BeanRegistrar;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@ -27,12 +28,12 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
import static org.springframework.util.StringUtils.trimArrayElements;
/**
* @link BeanDefinitionParser}
*
* @see ServiceAnnotationBeanPostProcessor
* @see ReferenceAnnotationBeanPostProcessor
* @since 2.5.9
@ -78,7 +79,7 @@ public class AnnotationBeanDefinitionParser extends AbstractSingleBeanDefinition
private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
// Register @Reference Annotation Bean Processor
registerInfrastructureBean(registry,
BeanRegistrar.registerInfrastructureBean(registry,
ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
}

View File

@ -53,8 +53,8 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
import static org.apache.dubbo.config.spring.util.BeanRegistrar.registerInfrastructureBean;
/**
* AbstractBeanDefinitionParser

View File

@ -31,8 +31,8 @@ import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.beans.factory.config.ConfigurableSourceBeanMetadataElement;
import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener;
import org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils;
import com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
@ -40,7 +40,7 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.w3c.dom.Element;
import static com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
/**
* DubboNamespaceHandler

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.config.spring.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ObjectUtils;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.springframework.util.ClassUtils.resolveClassName;
/**
* Annotated {@link BeanDefinition} Utilities
* <p>
*
* @since 2.6.6
*/
public abstract class AnnotatedBeanDefinitionRegistryUtils {
private static final Log logger = LogFactory.getLog(AnnotatedBeanDefinitionRegistryUtils.class);
/**
* Is present bean that was registered by the specified {@link Annotation annotated} {@link Class class}
*
* @param registry {@link BeanDefinitionRegistry}
* @param annotatedClass the {@link Annotation annotated} {@link Class class}
* @return if present, return <code>true</code>, or <code>false</code>
* @since 2.7.3
*/
public static boolean isPresentBean(BeanDefinitionRegistry registry, Class<?> annotatedClass) {
boolean present = false;
String[] beanNames = registry.getBeanDefinitionNames();
ClassLoader classLoader = annotatedClass.getClassLoader();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
if (beanDefinition instanceof AnnotatedBeanDefinition) {
AnnotationMetadata annotationMetadata = ((AnnotatedBeanDefinition) beanDefinition).getMetadata();
String className = annotationMetadata.getClassName();
Class<?> targetClass = resolveClassName(className, classLoader);
present = Objects.equals(targetClass, annotatedClass);
if (present) {
if (logger.isDebugEnabled()) {
logger.debug(format("The annotatedClass[class : %s , bean name : %s] was present in registry[%s]",
className, beanName, registry));
}
break;
}
}
}
return present;
}
/**
* Register Beans if not present in {@link BeanDefinitionRegistry registry}
*
* @param registry {@link BeanDefinitionRegistry}
* @param annotatedClasses {@link Annotation annotation} class
* @revision 2.7.3 {@link #isPresentBean(BeanDefinitionRegistry, Class)}
*/
public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {
if (ObjectUtils.isEmpty(annotatedClasses)) {
return;
}
Set<Class<?>> classesToRegister = new LinkedHashSet<>(asList(annotatedClasses));
// Remove all annotated-classes that have been registered
Iterator<Class<?>> iterator = classesToRegister.iterator();
while (iterator.hasNext()) {
Class<?> annotatedClass = iterator.next();
if (isPresentBean(registry, annotatedClass)) {
iterator.remove();
}
}
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
if (logger.isDebugEnabled()) {
logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
}
reader.register(classesToRegister.toArray(new Class[0]));
// clear
classesToRegister.clear();
}
}

View File

@ -0,0 +1,310 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.LinkedHashMap;
import java.util.Map;
import static java.lang.String.valueOf;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
import static org.springframework.core.annotation.AnnotatedElementUtils.getMergedAnnotation;
import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
import static org.springframework.core.annotation.AnnotationUtils.getDefaultValue;
import static org.springframework.util.ClassUtils.getAllInterfacesForClass;
import static org.springframework.util.ClassUtils.resolveClassName;
import static org.springframework.util.CollectionUtils.isEmpty;
import static org.springframework.util.ObjectUtils.containsElement;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import static org.springframework.util.StringUtils.hasText;
import static org.springframework.util.StringUtils.trimWhitespace;
/**
* Annotation Utilities Class
*
* @see org.springframework.core.annotation.AnnotationUtils
* @since 2.5.11
*/
public class AnnotationUtils {
@Deprecated
public static String resolveInterfaceName(Service service, Class<?> defaultInterfaceClass)
throws IllegalStateException {
String interfaceName;
if (hasText(service.interfaceName())) {
interfaceName = service.interfaceName();
} else if (!void.class.equals(service.interfaceClass())) {
interfaceName = service.interfaceClass().getName();
} else if (defaultInterfaceClass.isInterface()) {
interfaceName = defaultInterfaceClass.getName();
} else {
throw new IllegalStateException(
"The @Service undefined interfaceClass or interfaceName, and the type "
+ defaultInterfaceClass.getName() + " is not a interface.");
}
return interfaceName;
}
/**
* Resolve the interface name from {@link AnnotationAttributes}
*
* @param attributes {@link AnnotationAttributes} instance, may be {@link Service @Service} or {@link Reference @Reference}
* @param defaultInterfaceClass the default {@link Class class} of interface
* @return the interface name if found
* @throws IllegalStateException if interface name was not found
*/
public static String resolveInterfaceName(AnnotationAttributes attributes, Class<?> defaultInterfaceClass) {
Boolean generic = getAttribute(attributes, "generic");
if (generic != null && generic) {
// it's a generic reference
String interfaceClassName = getAttribute(attributes, "interfaceName");
Assert.hasText(interfaceClassName,
"@Reference interfaceName() must be present when reference a generic service!");
return interfaceClassName;
}
return resolveServiceInterfaceClass(attributes, defaultInterfaceClass).getName();
}
/**
* Get the attribute value
*
* @param attributes {@link AnnotationAttributes the annotation attributes}
* @param name the name of attribute
* @param <T> the type of attribute value
* @return the attribute value if found
* @since 2.7.3
*/
public static <T> T getAttribute(AnnotationAttributes attributes, String name) {
return (T) attributes.get(name);
}
/**
* Resolve the {@link Class class} of Dubbo Service interface from the specified
* {@link AnnotationAttributes annotation attributes} and annotated {@link Class class}.
*
* @param attributes {@link AnnotationAttributes annotation attributes}
* @param defaultInterfaceClass the annotated {@link Class class}.
* @return the {@link Class class} of Dubbo Service interface
* @throws IllegalArgumentException if can't resolved
*/
public static Class<?> resolveServiceInterfaceClass(AnnotationAttributes attributes, Class<?> defaultInterfaceClass)
throws IllegalArgumentException {
ClassLoader classLoader = defaultInterfaceClass != null ? defaultInterfaceClass.getClassLoader() : Thread.currentThread().getContextClassLoader();
Class<?> interfaceClass = getAttribute(attributes, "interfaceClass");
if (void.class.equals(interfaceClass)) { // default or set void.class for purpose.
interfaceClass = null;
String interfaceClassName = getAttribute(attributes, "interfaceName");
if (hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = resolveClassName(interfaceClassName, classLoader);
}
}
}
if (interfaceClass == null && defaultInterfaceClass != null) {
// Find all interfaces from the annotated class
// To resolve an issue : https://github.com/apache/dubbo/issues/3251
Class<?>[] allInterfaces = getAllInterfacesForClass(defaultInterfaceClass);
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
}
}
Assert.notNull(interfaceClass,
"@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(),
"The annotated type must be an interface!");
return interfaceClass;
}
@Deprecated
public static String resolveInterfaceName(Reference reference, Class<?> defaultInterfaceClass)
throws IllegalStateException {
String interfaceName;
if (!"".equals(reference.interfaceName())) {
interfaceName = reference.interfaceName();
} else if (!void.class.equals(reference.interfaceClass())) {
interfaceName = reference.interfaceClass().getName();
} else if (defaultInterfaceClass.isInterface()) {
interfaceName = defaultInterfaceClass.getName();
} else {
throw new IllegalStateException(
"The @Reference undefined interfaceClass or interfaceName, and the type "
+ defaultInterfaceClass.getName() + " is not a interface.");
}
return interfaceName;
}
/**
* Get the {@link Annotation} attributes
*
* @param annotation specified {@link Annotation}
* @param ignoreDefaultValue whether ignore default value or not
* @param ignoreAttributeNames the attribute names of annotation should be ignored
* @return non-null
* @since 2.6.6
* @deprecated
*/
@Deprecated
public static Map<String, Object> getAttributes(Annotation annotation, boolean ignoreDefaultValue,
String... ignoreAttributeNames) {
return getAttributes(annotation, null, ignoreDefaultValue, ignoreAttributeNames);
}
/**
* Get the {@link Annotation} attributes
*
* @param annotation specified {@link Annotation}
* @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment}
* @param ignoreDefaultValue whether ignore default value or not
* @param ignoreAttributeNames the attribute names of annotation should be ignored
* @return non-null
* @since 2.6.6
*/
public static Map<String, Object> getAttributes(Annotation annotation, PropertyResolver propertyResolver,
boolean ignoreDefaultValue, String... ignoreAttributeNames) {
if (annotation == null) {
return emptyMap();
}
Map<String, Object> attributes = getAnnotationAttributes(annotation);
Map<String, Object> actualAttributes = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
String attributeName = entry.getKey();
Object attributeValue = entry.getValue();
// ignore default attribute value
if (ignoreDefaultValue && nullSafeEquals(attributeValue, getDefaultValue(annotation, attributeName))) {
continue;
}
actualAttributes.put(attributeName, attributeValue);
}
return resolvePlaceholders(actualAttributes, propertyResolver, ignoreAttributeNames);
}
/**
* Resolve the placeholders from the specified annotation attributes
*
* @param sourceAnnotationAttributes the source of annotation attributes
* @param propertyResolver {@link PropertyResolver}
* @param ignoreAttributeNames the attribute names to be ignored
* @return a new resolved annotation attributes , non-null and read-only
* @since 2.7.3
*/
public static Map<String, Object> resolvePlaceholders(Map<String, Object> sourceAnnotationAttributes,
PropertyResolver propertyResolver,
String... ignoreAttributeNames) {
if (isEmpty(sourceAnnotationAttributes)) {
return emptyMap();
}
Map<String, Object> resolvedAnnotationAttributes = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : sourceAnnotationAttributes.entrySet()) {
String attributeName = entry.getKey();
// ignore attribute name to skip
if (containsElement(ignoreAttributeNames, attributeName)) {
continue;
}
Object attributeValue = entry.getValue();
if (attributeValue instanceof String) {
attributeValue = resolvePlaceholders(valueOf(attributeValue), propertyResolver);
} else if (attributeValue instanceof String[]) {
String[] values = (String[]) attributeValue;
for (int i = 0; i < values.length; i++) {
values[i] = resolvePlaceholders(values[i], propertyResolver);
}
attributeValue = values;
}
resolvedAnnotationAttributes.put(attributeName, attributeValue);
}
return unmodifiableMap(resolvedAnnotationAttributes);
}
/**
* Get {@link AnnotationAttributes the annotation attributes} after merging and resolving the placeholders
*
* @param annotatedElement {@link AnnotatedElement the annotated element}
* @param annotationType the {@link Class tyoe} pf {@link Annotation annotation}
* @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment}
* @param ignoreDefaultValue whether ignore default value or not
* @param ignoreAttributeNames the attribute names of annotation should be ignored
* @return If the specified annotation type is not found, return <code>null</code>
* @since 2.7.3
*/
public static AnnotationAttributes getMergedAttributes(AnnotatedElement annotatedElement,
Class<? extends Annotation> annotationType,
PropertyResolver propertyResolver,
boolean ignoreDefaultValue,
String... ignoreAttributeNames) {
Annotation annotation = getMergedAnnotation(annotatedElement, annotationType);
return annotation == null ? null : fromMap(getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames));
}
private static String resolvePlaceholders(String attributeValue, PropertyResolver propertyResolver) {
String resolvedValue = attributeValue;
if (propertyResolver != null) {
resolvedValue = propertyResolver.resolvePlaceholders(resolvedValue);
resolvedValue = trimWhitespace(resolvedValue);
}
return resolvedValue;
}
}

View File

@ -17,12 +17,19 @@
package org.apache.dubbo.config.spring.util;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.AbstractApplicationContext;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.springframework.util.ObjectUtils.isEmpty;
/**
* {@link BeanFactory} Utilities class
@ -32,7 +39,7 @@ import java.lang.reflect.Method;
* @see org.springframework.beans.factory.BeanFactoryUtils
* @since 2.5.7
*/
public class ApplicationContextUtils {
public class BeanFactoryUtils {
public static boolean addApplicationListener(ApplicationContext applicationContext, ApplicationListener listener) {
try {
@ -57,4 +64,51 @@ public class ApplicationContextUtils {
}
return false;
}
/**
* Get nullable Bean
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanName the name of Bean
* @param beanType the {@link Class type} of Bean
* @param <T> the {@link Class type} of Bean
* @return A bean if present , or <code>null</code>
*/
public static <T> T getNullableBean(ListableBeanFactory beanFactory, String beanName, Class<T> beanType) {
T bean = null;
try {
bean = beanFactory.getBean(beanName, beanType);
} catch (Throwable ignored) {
// Any exception will be ignored to handle
}
return bean;
}
/**
* Gets name-matched Beans from {@link ListableBeanFactory BeanFactory}
*
* @param beanFactory {@link ListableBeanFactory BeanFactory}
* @param beanNames the names of Bean
* @param beanType the {@link Class type} of Bean
* @param <T> the {@link Class type} of Bean
* @return the read-only and non-null {@link List} of Bean names
*/
public static <T> List<T> getBeans(ListableBeanFactory beanFactory, String[] beanNames, Class<T> beanType) {
if (isEmpty(beanNames)) {
return emptyList();
}
List<T> beans = new ArrayList<T>(beanNames.length);
for (String beanName : beanNames) {
T bean = getNullableBean(beanFactory, beanName, beanType);
if (bean != null) {
beans.add(bean);
}
}
return Collections.unmodifiableList(beans);
}
}

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.config.spring.util;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.AliasRegistry;
import static org.springframework.util.ObjectUtils.containsElement;
import static org.springframework.util.StringUtils.hasText;
/**
* Bean Registrar
*
* @since 2.5.7
*/
public class BeanRegistrar {
/**
* Register Infrastructure Bean
*
* @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
* @param beanType the type of bean
* @param beanName the name of bean
*/
public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName,
Class<?> beanType) {
if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}
/**
* Detect the alias is present or not in the given bean name from {@link AliasRegistry}
*
* @param registry {@link AliasRegistry}
* @param beanName the bean name
* @param alias alias to test
* @return if present, return <code>true</code>, or <code>false</code>
*/
public static boolean hasAlias(AliasRegistry registry, String beanName, String alias) {
return hasText(beanName) && hasText(alias) && containsElement(registry.getAliases(beanName), alias);
}
}

View File

@ -14,19 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
package org.apache.dubbo.config.spring.util;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @FormParam
* {@link Class} Utilities
* <p>
* The source code is cloned from
* https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/ClassUtils.java
*
* @since 2.7.5
* @since 2.6.6
*/
public class FormParamParameterProcessor extends ParamAnnotationParameterProcessor {
public abstract class ClassUtils {
@Override
public String getAnnotationType() {
return "javax.ws.rs.FormParam";
public static <T> Class<T> resolveGenericType(Class<?> declaredClass) {
ParameterizedType parameterizedType = (ParameterizedType) declaredClass.getGenericSuperclass();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
return (Class<T>) actualTypeArguments[0];
}
}

View File

@ -1,150 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static org.springframework.util.ClassUtils.getAllInterfacesForClass;
import static org.springframework.util.ClassUtils.resolveClassName;
import static org.springframework.util.StringUtils.hasText;
/**
* Dubbbo Annotation Utilities Class
*
* @see org.springframework.core.annotation.AnnotationUtils
* @since 2.5.11
*/
public class DubboAnnotationUtils {
@Deprecated
public static String resolveInterfaceName(Service service, Class<?> defaultInterfaceClass)
throws IllegalStateException {
String interfaceName;
if (hasText(service.interfaceName())) {
interfaceName = service.interfaceName();
} else if (!void.class.equals(service.interfaceClass())) {
interfaceName = service.interfaceClass().getName();
} else if (defaultInterfaceClass.isInterface()) {
interfaceName = defaultInterfaceClass.getName();
} else {
throw new IllegalStateException(
"The @Service undefined interfaceClass or interfaceName, and the type "
+ defaultInterfaceClass.getName() + " is not a interface.");
}
return interfaceName;
}
/**
* Resolve the interface name from {@link AnnotationAttributes}
*
* @param attributes {@link AnnotationAttributes} instance, may be {@link Service @Service} or {@link Reference @Reference}
* @param defaultInterfaceClass the default {@link Class class} of interface
* @return the interface name if found
* @throws IllegalStateException if interface name was not found
*/
public static String resolveInterfaceName(AnnotationAttributes attributes, Class<?> defaultInterfaceClass) {
Boolean generic = getAttribute(attributes, "generic");
if (generic != null && generic) {
// it's a generic reference
String interfaceClassName = getAttribute(attributes, "interfaceName");
Assert.hasText(interfaceClassName,
"@Reference interfaceName() must be present when reference a generic service!");
return interfaceClassName;
}
return resolveServiceInterfaceClass(attributes, defaultInterfaceClass).getName();
}
/**
* Resolve the {@link Class class} of Dubbo Service interface from the specified
* {@link AnnotationAttributes annotation attributes} and annotated {@link Class class}.
*
* @param attributes {@link AnnotationAttributes annotation attributes}
* @param defaultInterfaceClass the annotated {@link Class class}.
* @return the {@link Class class} of Dubbo Service interface
* @throws IllegalArgumentException if can't resolved
*/
public static Class<?> resolveServiceInterfaceClass(AnnotationAttributes attributes, Class<?> defaultInterfaceClass)
throws IllegalArgumentException {
ClassLoader classLoader = defaultInterfaceClass != null ? defaultInterfaceClass.getClassLoader() : Thread.currentThread().getContextClassLoader();
Class<?> interfaceClass = getAttribute(attributes, "interfaceClass");
if (void.class.equals(interfaceClass)) { // default or set void.class for purpose.
interfaceClass = null;
String interfaceClassName = getAttribute(attributes, "interfaceName");
if (hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = resolveClassName(interfaceClassName, classLoader);
}
}
}
if (interfaceClass == null && defaultInterfaceClass != null) {
// Find all interfaces from the annotated class
// To resolve an issue : https://github.com/apache/dubbo/issues/3251
Class<?>[] allInterfaces = getAllInterfacesForClass(defaultInterfaceClass);
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
}
}
Assert.notNull(interfaceClass,
"@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(),
"The annotated type must be an interface!");
return interfaceClass;
}
@Deprecated
public static String resolveInterfaceName(Reference reference, Class<?> defaultInterfaceClass)
throws IllegalStateException {
String interfaceName;
if (!"".equals(reference.interfaceName())) {
interfaceName = reference.interfaceName();
} else if (!void.class.equals(reference.interfaceClass())) {
interfaceName = reference.interfaceClass().getName();
} else if (defaultInterfaceClass.isInterface()) {
interfaceName = defaultInterfaceClass.getName();
} else {
throw new IllegalStateException(
"The @Reference undefined interfaceClass or interfaceName, and the type "
+ defaultInterfaceClass.getName() + " is not a interface.");
}
return interfaceName;
}
}

View File

@ -14,22 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.tools;
import java.io.Serializable;
package org.apache.dubbo.config.spring.util;
/**
* Ancestor
* Object Utilities
*
* @since 2.6.6
*/
public class Ancestor implements Serializable {
public abstract class ObjectUtils {
private boolean z;
public boolean isZ() {
return z;
/**
* Convert from variable arguments to array
*
* @param values variable arguments
* @param <T> The class
* @return array
*/
public static <T> T[] of(T... values) {
return values;
}
public void setZ(boolean z) {
this.z = z;
}
}

View File

@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import static java.util.Collections.unmodifiableMap;
/**
* {@link PropertySources} Utilities
* <p>
*
* @since 2.6.6
*/
public abstract class PropertySourcesUtils {
/**
* Get prefixed {@link Properties}
*
* @param propertySources {@link PropertySource} Iterable
* @param prefix the prefix of property name
* @return Map
* @see Properties
*/
public static Map<String, Object> getPrefixedProperties(Iterable<PropertySource<?>> propertySources, String prefix) {
MutablePropertySources mutablePropertySources = new MutablePropertySources();
for (PropertySource<?> source : propertySources) {
mutablePropertySources.addLast(source);
}
return getPrefixedProperties(mutablePropertySources, prefix);
}
/**
* Get prefixed {@link Properties}
*
* @param propertySources {@link PropertySources}
* @param prefix the prefix of property name
* @return Map
* @see Properties
*/
public static Map<String, Object> getPrefixedProperties(PropertySources propertySources, String prefix) {
PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
Map<String, Object> prefixedProperties = new LinkedHashMap<>();
String normalizedPrefix = buildPrefix(prefix);
Iterator<PropertySource<?>> iterator = propertySources.iterator();
while (iterator.hasNext()) {
PropertySource<?> source = iterator.next();
if (source instanceof EnumerablePropertySource) {
for (String name : ((EnumerablePropertySource<?>) source).getPropertyNames()) {
if (!prefixedProperties.containsKey(name) && name.startsWith(normalizedPrefix)) {
String subName = name.substring(normalizedPrefix.length());
if (!prefixedProperties.containsKey(subName)) { // take first one
Object value = source.getProperty(name);
if (value instanceof String) {
// Resolve placeholder
value = propertyResolver.resolvePlaceholders((String) value);
}
prefixedProperties.put(subName, value);
}
}
}
}
}
return unmodifiableMap(prefixedProperties);
}
/**
* Build the prefix
*
* @param prefix the prefix
* @return the prefix
*/
public static String buildPrefix(String prefix) {
if (prefix.endsWith(".")) {
return prefix;
} else {
return prefix + ".";
}
}
}

View File

@ -97,19 +97,17 @@ public class ReferenceAnnotationBeanPostProcessorTest {
TestBean testBean = context.getBean(TestBean.class);
DemoService demoService = testBean.getDemoService();
Map<String, DemoService> demoServicesMap = context.getBeansOfType(DemoService.class);
Assert.assertEquals("Hello,Mercy", demoService.sayName("Mercy"));
Assert.assertEquals("Greeting, Mercy", defaultHelloService.sayHello("Mercy"));
Assert.assertEquals("Hello, Mercy", helloServiceImpl.sayHello("Mercy"));
Assert.assertEquals("Greeting, Mercy", helloService.sayHello("Mercy"));
Assert.assertNotNull(testBean.getDemoServiceFromAncestor());
Assert.assertNotNull(testBean.getDemoServiceFromParent());
Assert.assertNotNull(testBean.getDemoService());
Assert.assertNotNull(testBean.autowiredDemoService);
Assert.assertEquals(1, demoServicesMap.size());
Assert.assertEquals("Hello,Mercy", demoService.sayName("Mercy"));
Assert.assertEquals("Greeting, Mercy", defaultHelloService.sayHello("Mercy"));
Assert.assertEquals("Hello, Mercy", helloServiceImpl.sayHello("Mercy"));
Assert.assertEquals("Greeting, Mercy", helloService.sayHello("Mercy"));
Assert.assertEquals("Hello,Mercy", testBean.getDemoServiceFromAncestor().sayName("Mercy"));
Assert.assertEquals("Hello,Mercy", testBean.getDemoServiceFromParent().sayName("Mercy"));
@ -120,6 +118,9 @@ public class ReferenceAnnotationBeanPostProcessorTest {
Assert.assertEquals("Hello,Mercy", myDemoService.sayName("Mercy"));
Map<String, DemoService> demoServicesMap = context.getBeansOfType(DemoService.class);
Assert.assertEquals(1, demoServicesMap.size());
for (DemoService demoService1 : demoServicesMap.values()) {
@ -164,7 +165,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
InjectionMetadata.InjectedElement injectedElement = entry.getKey();
Assert.assertEquals("com.alibaba.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor$AnnotatedFieldElement",
Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedFieldElement",
injectedElement.getClass().getName());
}
@ -186,7 +187,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
InjectionMetadata.InjectedElement injectedElement = entry.getKey();
Assert.assertEquals("com.alibaba.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor$AnnotatedMethodElement",
Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedMethodElement",
injectedElement.getClass().getName());
}

View File

@ -32,11 +32,10 @@ import org.springframework.context.annotation.PropertySource;
import java.util.Map;
import static com.alibaba.spring.util.BeanRegistrar.hasAlias;
import static org.apache.dubbo.config.spring.util.BeanRegistrar.hasAlias;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link EnableDubboConfig} Test
*

View File

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Service;
import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.isPresentBean;
import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link AnnotatedBeanDefinitionRegistryUtils} Test
*
* @since 2.7.3
*/
public class AnnotatedBeanDefinitionRegistryUtilsTest {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@BeforeEach
public void init() {
context.setAllowBeanDefinitionOverriding(false);
}
@AfterEach
public void destroy() {
context.close();
}
@Test
public void testIsPresentBean() {
assertFalse(isPresentBean(context, A.class));
context.register(A.class);
for (int i = 0; i < 9; i++) {
assertTrue(isPresentBean(context, A.class));
}
}
@Test
public void testRegisterBeans() {
registerBeans(context, A.class, A.class);
registerBeans(context, A.class);
context.refresh();
A a = context.getBean(A.class);
Assert.assertNotNull(a);
}
@Service
static class A {
}
}

View File

@ -1,46 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import static org.apache.dubbo.config.spring.util.ApplicationContextUtils.addApplicationListener;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link ApplicationContextUtils} Test
*
* @since 2.5.7
*/
public class ApplicationContextUtilsTest {
private ApplicationContext applicationContext;
@BeforeEach
public void init() {
applicationContext = new GenericApplicationContext();
}
@Test
public void testAddApplicationListener() {
assertTrue(addApplicationListener(applicationContext, event -> {
}));
}
}

View File

@ -0,0 +1,111 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* {@link BeanFactoryUtils} Test
*
* @since 2.5.7
*/
public class BeanFactoryUtilsTest {
private AnnotationConfigApplicationContext applicationContext;
@BeforeEach
public void init() {
applicationContext = new AnnotationConfigApplicationContext();
}
@Test
public void testGetNullableBean() {
applicationContext.register(TestBean.class);
applicationContext.refresh();
TestBean testBean = BeanFactoryUtils.getNullableBean(applicationContext, "testBean", TestBean.class);
Assertions.assertNotNull(testBean);
Assertions.assertEquals("Hello,World", testBean.getName());
}
@Test
public void testGetNullableBeanIfAbsent() {
applicationContext.refresh();
TestBean testBean = BeanFactoryUtils.getNullableBean(applicationContext, "testBean", TestBean.class);
Assertions.assertNull(testBean);
}
@Test
public void testGetBeans() {
applicationContext.register(TestBean.class, TestBean2.class);
applicationContext.refresh();
List<TestBean> testBeans = BeanFactoryUtils.getBeans(applicationContext, new String[]{"testBean"}, TestBean.class);
Assertions.assertEquals(1, testBeans.size());
Assertions.assertEquals("Hello,World", testBeans.get(0).getName());
}
@Test
public void testGetBeansIfAbsent() {
applicationContext.refresh();
List<TestBean> testBeans = BeanFactoryUtils.getBeans(applicationContext, new String[]{"testBean"}, TestBean.class);
Assertions.assertTrue(testBeans.isEmpty());
}
@Component("testBean2")
private static class TestBean2 extends TestBean {
}
@Component("testBean")
private static class TestBean {
private String name = "Hello,World";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

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.config.spring.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* {@link PropertySourcesUtils} Test
*
* @see PropertySourcesUtils
* @since 2.5.8
*/
public class PropertySourcesUtilsTest {
@Test
public void testGetPrefixedProperties() {
MutablePropertySources propertySources = new MutablePropertySources();
Map<String, Object> source = new HashMap<String, Object>();
Map<String, Object> source2 = new HashMap<String, Object>();
MapPropertySource propertySource = new MapPropertySource("propertySource", source);
MapPropertySource propertySource2 = new MapPropertySource("propertySource2", source2);
propertySources.addLast(propertySource);
propertySources.addLast(propertySource2);
Map<String, Object> result = PropertySourcesUtils.getPrefixedProperties(propertySources, "user");
Assertions.assertEquals(Collections.emptyMap(), result);
source.put("age", "31");
source.put("user.name", "Mercy");
source.put("user.age", "${age}");
source2.put("user.name", "mercyblitz");
source2.put("user.age", "32");
Map<String, Object> expected = new HashMap<String, Object>();
expected.put("name", "Mercy");
expected.put("age", "31");
result = PropertySourcesUtils.getPrefixedProperties(propertySources, "user");
Assertions.assertEquals(expected, result);
result = PropertySourcesUtils.getPrefixedProperties(propertySources, "");
Assertions.assertEquals(Collections.emptyMap(), result);
result = PropertySourcesUtils.getPrefixedProperties(propertySources, "no-exists");
Assertions.assertEquals(Collections.emptyMap(), result);
}
}

View File

@ -144,9 +144,6 @@
<!-- Eureka -->
<eureka.version>1.9.12</eureka.version>
<!-- Alibaba -->
<alibaba_spring_context_support_version>1.0.4-SNAPSHOT</alibaba_spring_context_support_version>
<jaxb_version>2.2.7</jaxb_version>
<activation_version>1.2.0</activation_version>
<test_container_version>1.11.2</test_container_version>
@ -280,14 +277,6 @@
<artifactId>eureka-core</artifactId>
<version>${eureka.version}</version>
</dependency>
<!-- Alibaba -->
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>${alibaba_spring_context_support_version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>

View File

@ -27,12 +27,11 @@ import java.util.List;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_MAPPING_GROUP;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* The {@link ServiceNameMapping} implementation based on {@link DynamicConfiguration}
*
* @since 2.7.5
*/
public class DynamicConfigurationServiceNameMapping implements ServiceNameMapping {
@ -55,14 +54,13 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
// the Dubbo Service Key as group
// the service(application) name as key
// It does not matter whatever the content is, we just need a record
String key = ApplicationModel.getApplication();
String content = String.valueOf(System.currentTimeMillis());
// It does matter whatever the content is, we just need a record
String app = ApplicationModel.getApplication();
execute(() -> {
dynamicConfiguration.publishConfig(key, buildGroup(serviceInterface, group, version, protocol), content);
dynamicConfiguration.publishConfig(buildKey(serviceInterface, group, version, protocol), app);
if (logger.isInfoEnabled()) {
logger.info(String.format("The Dubbo service key[%s] mapped to service name[%s] with content : %s",
key, group, content));
logger.info(String.format("Dubbo service[%s] mapped to interface name[%s].",
app, serviceInterface, app));
}
});
}
@ -72,17 +70,15 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
String key = ApplicationModel.getApplication();
Set<String> serviceNames = new LinkedHashSet<>();
execute(() -> {
Set<String> keys = dynamicConfiguration.getConfigKeys(buildGroup(serviceInterface, group, version, protocol), key);
Set<String> keys = dynamicConfiguration.getConfigKeys(DEFAULT_MAPPING_GROUP, buildKey(serviceInterface, group, version, protocol));
serviceNames.addAll(keys);
});
return Collections.unmodifiableSet(serviceNames);
}
protected static String buildGroup(String serviceInterface, String group, String version, String protocol) {
protected static String buildKey(String serviceInterface, String group, String version, String protocol) {
// the issue : https://github.com/apache/dubbo/issues/4671
// StringBuilder groupBuilder = new StringBuilder(serviceInterface)
// .append(KEY_SEPARATOR).append(defaultString(group))

View File

@ -1,225 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.rest;
import org.apache.dubbo.common.utils.CollectionUtils;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
import static org.apache.dubbo.metadata.util.HttpUtils.normalizePath;
/**
* The metadata class for REST request
*
* @since 2.7.5
*/
public class RequestMetadata implements Serializable {
private static final long serialVersionUID = -240099840085329958L;
private String method;
private String path;
private Map<String, List<String>> params = new LinkedHashMap<>();
private Map<String, List<String>> headers = new LinkedHashMap<>();
private Set<String> consumes = new LinkedHashSet<>();
private Set<String> produces = new LinkedHashSet<>();
/**
* Default Constructor
*/
public RequestMetadata() {
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method == null ? null : method.toUpperCase();
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = normalizePath(path);
}
public Map<String, List<String>> getParams() {
return unmodifiableMap(params);
}
public void setParams(Map<String, List<String>> params) {
params(params);
}
private static void add(Map<String, List<String>> multiValueMap, String key, String value) {
if (isBlank(key)) {
return;
}
List<String> values = get(multiValueMap, key, true);
values.add(value);
}
private static <T extends Collection<String>> void addAll(Map<String, List<String>> multiValueMap,
Map<String, T> source) {
for (Map.Entry<String, T> entry : source.entrySet()) {
String key = entry.getKey();
for (String value : entry.getValue()) {
add(multiValueMap, key, value);
}
}
}
private static String getFirst(Map<String, List<String>> multiValueMap, String key) {
List<String> values = get(multiValueMap, key);
return CollectionUtils.isNotEmpty(values) ? values.get(0) : null;
}
private static List<String> get(Map<String, List<String>> multiValueMap, String key) {
return get(multiValueMap, key, false);
}
private static List<String> get(Map<String, List<String>> multiValueMap, String key, boolean createIfAbsent) {
return createIfAbsent ? multiValueMap.computeIfAbsent(key, k -> new LinkedList<>()) : multiValueMap.get(key);
}
public Map<String, List<String>> getHeaders() {
return unmodifiableMap(headers);
}
public void setHeaders(Map<String, List<String>> headers) {
headers(headers);
}
public Set<String> getConsumes() {
return consumes;
}
public void setConsumes(Set<String> consumes) {
this.consumes = consumes;
}
public Set<String> getProduces() {
return produces;
}
public void setProduces(Set<String> produces) {
this.produces = produces;
}
public Set<String> getParamNames() {
return params.keySet();
}
public Set<String> getHeaderNames() {
return headers.keySet();
}
// public List<MediaType> getConsumeMediaTypes() {
// return toMediaTypes(consumes);
// }
//
// public List<MediaType> getProduceMediaTypes() {
// return toMediaTypes(produces);
// }
public String getParameter(String name) {
return this.getFirst(params, name);
}
public String getHeader(String name) {
return this.getFirst(headers, name);
}
public RequestMetadata addParam(String name, String value) {
add(params, name, value);
return this;
}
public RequestMetadata addHeader(String name, String value) {
add(headers, name, value);
return this;
}
private <T extends Collection<String>> RequestMetadata params(Map<String, T> params) {
addAll(this.params, params);
return this;
}
private <T extends Collection<String>> RequestMetadata headers(Map<String, List<String>> headers) {
if (headers != null && !headers.isEmpty()) {
Map<String, List<String>> httpHeaders = new LinkedHashMap<>();
// Add all headers
addAll(headers, httpHeaders);
// Handles "Content-Type" and "Accept" headers if present
// mediaTypes(httpHeaders, HttpHeaders.CONTENT_TYPE, this.consumes);
// mediaTypes(httpHeaders, HttpHeaders.ACCEPT, this.produces);
this.headers.putAll(httpHeaders);
}
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof RequestMetadata)) {
return false;
}
RequestMetadata that = (RequestMetadata) o;
return Objects.equals(method, that.method) && Objects.equals(path, that.path)
&& Objects.equals(consumes, that.consumes)
&& Objects.equals(produces, that.produces) &&
// Metadata should not compare the values
Objects.equals(getParamNames(), that.getParamNames())
&& Objects.equals(getHeaderNames(), that.getHeaderNames());
}
@Override
public int hashCode() {
// The values of metadata should not use for the hashCode() method
return Objects.hash(method, path, consumes, produces, getParamNames(),
getHeaderNames());
}
@Override
public String toString() {
return "RequestMetadata{" + "method='" + method + '\'' + ", path='" + path + '\''
+ ", params=" + params + ", headers=" + headers + ", consumes=" + consumes
+ ", produces=" + produces + '}';
}
}

View File

@ -1,187 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.rest;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Collections.emptyList;
/**
* The metadata class for {@link RequestMetadata HTTP(REST) request} and
* its binding {@link MethodDefinition method definition}
*
* @since 2.7.5
*/
public class RestMethodMetadata implements Serializable {
private static final long serialVersionUID = 2935252016200830694L;
private MethodDefinition method;
private RequestMetadata request;
private Integer urlIndex;
private Integer bodyIndex;
private Integer headerMapIndex;
private String bodyType;
private Map<Integer, Collection<String>> indexToName;
private List<String> formParams;
private Map<Integer, Boolean> indexToEncoded;
public MethodDefinition getMethod() {
if (method == null) {
method = new MethodDefinition();
}
return method;
}
public void setMethod(MethodDefinition method) {
this.method = method;
}
public RequestMetadata getRequest() {
if (request == null) {
request = new RequestMetadata();
}
return request;
}
public void setRequest(RequestMetadata request) {
this.request = request;
}
public Integer getUrlIndex() {
return urlIndex;
}
public void setUrlIndex(Integer urlIndex) {
this.urlIndex = urlIndex;
}
public Integer getBodyIndex() {
return bodyIndex;
}
public void setBodyIndex(Integer bodyIndex) {
this.bodyIndex = bodyIndex;
}
public Integer getHeaderMapIndex() {
return headerMapIndex;
}
public void setHeaderMapIndex(Integer headerMapIndex) {
this.headerMapIndex = headerMapIndex;
}
public String getBodyType() {
return bodyType;
}
public void setBodyType(String bodyType) {
this.bodyType = bodyType;
}
public Map<Integer, Collection<String>> getIndexToName() {
if (indexToName == null) {
indexToName = new HashMap<>();
}
return indexToName;
}
public void setIndexToName(Map<Integer, Collection<String>> indexToName) {
this.indexToName = indexToName;
}
public void addIndexToName(Integer index, String name) {
Map<Integer, Collection<String>> indexToName = getIndexToName();
Collection<String> parameterNames = indexToName.computeIfAbsent(index, i -> new ArrayList<>(1));
parameterNames.add(name);
}
public boolean hasIndexedName(Integer index, String name) {
Map<Integer, Collection<String>> indexToName = getIndexToName();
return indexToName.getOrDefault(index, emptyList()).contains(name);
}
public List<String> getFormParams() {
return formParams;
}
public void setFormParams(List<String> formParams) {
this.formParams = formParams;
}
public Map<Integer, Boolean> getIndexToEncoded() {
return indexToEncoded;
}
public void setIndexToEncoded(Map<Integer, Boolean> indexToEncoded) {
this.indexToEncoded = indexToEncoded;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RestMethodMetadata)) return false;
RestMethodMetadata that = (RestMethodMetadata) o;
return Objects.equals(getMethod(), that.getMethod()) &&
Objects.equals(getRequest(), that.getRequest()) &&
Objects.equals(getUrlIndex(), that.getUrlIndex()) &&
Objects.equals(getBodyIndex(), that.getBodyIndex()) &&
Objects.equals(getHeaderMapIndex(), that.getHeaderMapIndex()) &&
Objects.equals(getBodyType(), that.getBodyType()) &&
Objects.equals(getIndexToName(), that.getIndexToName()) &&
Objects.equals(getFormParams(), that.getFormParams()) &&
Objects.equals(getIndexToEncoded(), that.getIndexToEncoded());
}
@Override
public int hashCode() {
return Objects.hash(getMethod(), getRequest(), getUrlIndex(), getBodyIndex(), getHeaderMapIndex(), getBodyType(), getIndexToName(), getFormParams(), getIndexToEncoded());
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("RestMethodMetadata{");
sb.append("method=").append(method);
sb.append(", request=").append(request);
sb.append(", urlIndex=").append(urlIndex);
sb.append(", bodyIndex=").append(bodyIndex);
sb.append(", headerMapIndex=").append(headerMapIndex);
sb.append(", bodyType='").append(bodyType).append('\'');
sb.append(", indexToName=").append(indexToName);
sb.append(", formParams=").append(formParams);
sb.append(", indexToEncoded=").append(indexToEncoded);
sb.append('}');
return sb.toString();
}
}

View File

@ -1,103 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.rest;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
/**
* The metadata class for {@link RequestMetadata HTTP(REST) request} and
* its binding Dubbo service metadata
*
* @since 2.7.5
*/
public class ServiceRestMetadata implements Serializable {
private static final long serialVersionUID = -4549723140727443569L;
private String serviceInterface;
private String version;
private String group;
private Set<RestMethodMetadata> meta;
public String getServiceInterface() {
return serviceInterface;
}
public void setServiceInterface(String serviceInterface) {
this.serviceInterface = serviceInterface;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public Set<RestMethodMetadata> getMeta() {
if (meta == null) {
meta = new LinkedHashSet<>();
}
return meta;
}
public void setMeta(Set<RestMethodMetadata> meta) {
this.meta = meta;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ServiceRestMetadata)) return false;
ServiceRestMetadata that = (ServiceRestMetadata) o;
return Objects.equals(getServiceInterface(), that.getServiceInterface()) &&
Objects.equals(getVersion(), that.getVersion()) &&
Objects.equals(getGroup(), that.getGroup()) &&
Objects.equals(getMeta(), that.getMeta());
}
@Override
public int hashCode() {
return Objects.hash(getServiceInterface(), getVersion(), getGroup(), getMeta());
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ServiceRestMetadata{");
sb.append("serviceInterface='").append(serviceInterface).append('\'');
sb.append(", version='").append(version).append('\'');
sb.append(", group='").append(group).append('\'');
sb.append(", meta=").append(meta);
sb.append('}');
return sb.toString();
}
}

View File

@ -4,17 +4,20 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
import java.util.Collection;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* @author cvictory ON 2019-08-14
* @since 2.7.5
*/
public class BaseWritableMetadataService {
final Logger logger = LoggerFactory.getLogger(getClass());

View File

@ -1,6 +1,7 @@
package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.metadata.WritableMetadataService;
import java.util.SortedSet;

View File

@ -1,266 +0,0 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.util;
import org.apache.dubbo.common.utils.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
import static org.apache.dubbo.common.utils.StringUtils.AND;
import static org.apache.dubbo.common.utils.StringUtils.EQUAL;
import static org.apache.dubbo.common.utils.StringUtils.QUESTION_MASK;
import static org.apache.dubbo.common.utils.StringUtils.SLASH;
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
import static org.apache.dubbo.common.utils.StringUtils.replace;
/**
* Http Utilities class
*
* @since 2.7.5
*/
public abstract class HttpUtils {
private static final String UTF_8 = "UTF-8";
/**
* HTTP GET method.
*/
public static final String GET = "GET";
/**
* HTTP POST method.
*/
public static final String POST = "POST";
/**
* HTTP PUT method.
*/
public static final String PUT = "PUT";
/**
* HTTP DELETE method.
*/
public static final String DELETE = "DELETE";
/**
* HTTP HEAD method.
*/
public static final String HEAD = "HEAD";
/**
* HTTP OPTIONS method.
*/
public static final String OPTIONS = "OPTIONS";
/**
* The HTTP methods to support
*/
public static final Set<String> HTTP_METHODS = unmodifiableSet(new LinkedHashSet<>(asList(
GET, POST, POST, PUT, DELETE, HEAD, OPTIONS
)));
public static String buildPath(String rootPath, String... subPaths) {
Set<String> paths = new LinkedHashSet<>();
paths.add(rootPath);
paths.addAll(asList(subPaths));
return normalizePath(paths.stream()
.filter(StringUtils::isNotEmpty)
.collect(Collectors.joining(SLASH)));
}
/**
* Normalize path:
* <ol>
* <li>To remove query string if presents</li>
* <li>To remove duplicated slash("/") if exists</li>
* </ol>
*
* @param path path to be normalized
* @return a normalized path if required
*/
public static String normalizePath(String path) {
if (isEmpty(path)) {
return SLASH;
}
String normalizedPath = path;
int index = normalizedPath.indexOf(QUESTION_MASK);
if (index > -1) {
normalizedPath = normalizedPath.substring(0, index);
}
return replace(normalizedPath, "//", "/");
}
// /**
// * Get Parameters from the specified query string.
// * <p>
// *
// * @param queryString The query string
// * @return The query parameters
// */
// public static MultivaluedMap<String, String> getParameters(String queryString) {
// return getParameters(split(queryString, AND_CHAR));
// }
// /**
// * Get Parameters from the specified pairs of name-value.
// * <p>
// *
// * @param pairs The pairs of name-value
// * @return The query parameters
// */
// public static MultivaluedMap<String, String> getParameters(Iterable<String> pairs) {
// MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
// if (pairs != null) {
// for (String pair : pairs) {
// String[] nameAndValue = split(pair, EQUAL_CHAR);
// String name = decode(nameAndValue[0]);
// String value = nameAndValue.length < 2 ? null : nameAndValue[1];
// value = decode(value);
// addParam(parameters, name, value);
// }
// }
// return parameters;
// }
// /**
// * Get Parameters from the specified pairs of name-value.
// * <p>
// *
// * @param pairs The pairs of name-value
// * @return The query parameters
// */
// public static MultivaluedMap<String, String> getParameters(String... pairs) {
// return getParameters(asList(pairs));
// }
// /**
// * Parse a read-only {@link MultivaluedMap} of {@link HttpCookie} from {@link
// HttpHeaders}
// *
// * @param httpHeaders {@link HttpHeaders}
// * @return non-null, the key is a cookie name , the value is {@link HttpCookie}
// */
// public static MultivaluedMap<String, HttpCookie> parseCookies(HttpHeaders
// httpHeaders) {
//
// String cookie = httpHeaders.getFirst(COOKIE);
//
// String[] cookieNameAndValues = StringUtils.delimitedListToStringArray(cookie,
// SEMICOLON);
//
// MultivaluedMap<String, HttpCookie> cookies = new
// LinkedMultiValueMap<>(cookieNameAndValues.length);
//
// for (String cookeNameAndValue : cookieNameAndValues) {
// String[] nameAndValue =
// delimitedListToStringArray(trimWhitespace(cookeNameAndValue), EQUAL);
// String name = nameAndValue[0];
// String value = nameAndValue.length < 2 ? null : nameAndValue[1];
// HttpCookie httpCookie = new HttpCookie(name, value);
// cookies.add(name, httpCookie);
// }
//
// return cookies;
// }
/**
* To the name and value line sets
*
* @param nameAndValuesMap the map of name and values
* @return non-null
*/
public static Set<String> toNameAndValuesSet(
Map<String, List<String>> nameAndValuesMap) {
Set<String> nameAndValues = new LinkedHashSet<>();
for (Map.Entry<String, List<String>> entry : nameAndValuesMap.entrySet()) {
String name = entry.getKey();
List<String> values = entry.getValue();
for (String value : values) {
String nameAndValue = name + EQUAL + value;
nameAndValues.add(nameAndValue);
}
}
return nameAndValues;
}
public static String[] toNameAndValues(Map<String, List<String>> nameAndValuesMap) {
return toNameAndValuesSet(nameAndValuesMap).toArray(new String[0]);
}
/**
* Generate a string of query string from the specified request parameters {@link Map}
*
* @param params the specified request parameters {@link Map}
* @return non-null
*/
public static String toQueryString(Map<String, List<String>> params) {
StringBuilder builder = new StringBuilder();
for (String line : toNameAndValuesSet(params)) {
builder.append(line).append(AND);
}
return builder.toString();
}
/**
* Decode value
*
* @param value the value requires to decode
* @return the decoded value
*/
public static String decode(String value) {
if (value == null) {
return value;
}
String decodedValue = value;
try {
decodedValue = URLDecoder.decode(value, UTF_8);
} catch (UnsupportedEncodingException ex) {
}
return decodedValue;
}
/**
* encode value
*
* @param value the value requires to encode
* @return the encoded value
*/
public static String encode(String value) {
String encodedValue = value;
try {
encodedValue = URLEncoder.encode(value, UTF_8);
} catch (UnsupportedEncodingException ex) {
}
return encodedValue;
}
// private static void addParam(MultivaluedMap<String, String> paramsMap, String name,
// String value) {
// String paramValue = trim(value);
// if (isEmpty(paramValue)) {
// paramValue = EMPTY_VALUE;
// }
// paramsMap.add(trim(name), paramValue);
// }
}

View File

@ -28,7 +28,7 @@ import java.util.TreeSet;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.metadata.DynamicConfigurationServiceNameMapping.buildGroup;
import static org.apache.dubbo.metadata.DynamicConfigurationServiceNameMapping.buildKey;
import static org.apache.dubbo.metadata.ServiceNameMapping.getDefaultExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -54,10 +54,10 @@ public class DynamicConfigurationServiceNameMappingTest {
@Test
public void testBuildGroup() {
assertEquals("test", buildGroup("test", null, null, null));
assertEquals("test", buildGroup("test", "default", null, null));
assertEquals("test", buildGroup("test", "default", "1.0.0", null));
assertEquals("test", buildGroup("test", "default", "1.0.0", "dubbo"));
assertEquals("test", buildKey("test", null, null, null));
assertEquals("test", buildKey("test", "default", null, null));
assertEquals("test", buildKey("test", "default", "1.0.0", null));
assertEquals("test", buildKey("test", "default", "1.0.0", "dubbo"));
}
@Test

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metadata.report.identifier;
import org.apache.dubbo.metadata.MetadataConstants;
import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

View File

@ -2,6 +2,7 @@ package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.metadata.store;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
@ -33,6 +34,8 @@ import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
/**
* 2018/9/14
*/

View File

@ -1,161 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-metadata-processor</artifactId>
<packaging>jar</packaging>
<name>dubbo-metadata-processor</name>
<description>The metadata processor module of Dubbo project</description>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-api</artifactId>
<version>${project.parent.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-cluster</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${project.parent.version}</version>
<exclusions>
<exclusion>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>hessian-lite</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</exclusion>
<exclusion>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
</exclusion>
<exclusion>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
</exclusion>
<exclusion>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
</exclusion>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-api</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-monitor-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-injvm</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-filter-validation</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-filter-cache</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- JAX-RS API -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,108 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static javax.lang.model.util.ElementFilter.methodsIn;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SUPPORTED_ANNOTATION_TYPES;
/**
* Abstract {@link Processor} for the classes that were annotated by Dubbo's @Service
*
* @since 2.7.5
*/
public abstract class AbstractServiceAnnotationProcessor extends AbstractProcessor {
protected Elements elements;
private List<? extends Element> objectMembers;
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.elements = processingEnv.getElementUtils();
this.objectMembers = elements.getAllMembers(elements.getTypeElement(Object.class.getName()));
}
protected List<? extends Element> getActualMembers(TypeElement type) {
List<? extends Element> members = new LinkedList<>(elements.getAllMembers(type));
members.removeAll(objectMembers);
return members;
}
protected List<? extends ExecutableElement> getActualMethods(TypeElement type) {
return methodsIn(getActualMembers(type));
}
protected Map<String, ExecutableElement> getActualMethodsMap(TypeElement type) {
Map<String, ExecutableElement> methodsMap = new HashMap<>();
getActualMethods(type).forEach(method -> {
methodsMap.put(method.toString(), method);
});
return methodsMap;
}
public static String getMethodSignature(ExecutableElement method) {
if (!ElementKind.METHOD.equals(method.getKind())) {
throw new IllegalArgumentException("The argument must be Method Kind");
}
StringBuilder methodSignatureBuilder = new StringBuilder();
method.getModifiers().forEach(member -> {
methodSignatureBuilder.append(member).append(" ");
});
methodSignatureBuilder.append(method.getReturnType())
.append(" ")
.append(method.toString());
return methodSignatureBuilder.toString();
}
protected TypeElement getTypeElement(CharSequence className) {
return elements.getTypeElement(className);
}
protected PackageElement getPackageElement(Element type) {
return this.elements.getPackageOf(type);
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
@Override
public final Set<String> getSupportedAnnotationTypes() {
return SUPPORTED_ANNOTATION_TYPES;
}
}

View File

@ -1,105 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.tools.FileObject;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.warn;
/**
* A storage class for metadata under class path
*/
public class ClassPathMetadataStorage {
private final Filer filer;
public ClassPathMetadataStorage(ProcessingEnvironment processingEnv) {
this.filer = processingEnv.getFiler();
}
public void write(Supplier<String> contentSupplier, String resourceName) {
try (Writer writer = getWriter(resourceName)) {
writer.write(contentSupplier.get());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public <T> Optional<T> read(String resourceName, Function<Reader, T> consumer) {
if (exists(resourceName)) {
try (Reader reader = getReader(resourceName)) {
return ofNullable(consumer.apply(reader));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return empty();
}
private boolean exists(String resourceName) {
return getResource(resourceName)
.map(FileObject::toUri)
.map(File::new)
.map(File::exists)
.orElse(false);
}
private Reader getReader(String resourceName) {
return getResource(resourceName).map(fileObject -> {
try {
return fileObject.openReader(false);
} catch (IOException e) {
}
return null;
}).orElse(null);
}
private FileObject createResource(String resourceName) throws IOException {
return filer.createResource(CLASS_OUTPUT, "", resourceName);
}
private Optional<FileObject> getResource(String resourceName) {
try {
FileObject fileObject = filer.getResource(CLASS_OUTPUT, "", resourceName);
return ofNullable(fileObject);
} catch (IOException e) {
warn(e.getMessage());
}
return empty();
}
private Writer getWriter(String resourceName) throws IOException {
FileObject fileObject = createResource(resourceName);
info("The resource[path : %s , deleted : %s] will be written", fileObject.toUri().getPath(), fileObject.delete());
return fileObject.openWriter();
}
}

View File

@ -1,60 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing;
import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
import com.google.gson.Gson;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.TypeElement;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static javax.lang.model.util.ElementFilter.typesIn;
import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
/**
* The {@link Processor} class to generate the metadata of {@link ServiceDefinition} whose classes are annotated by Dubbo's @Service
*
* @see Processor
* @since 2.7.5
*/
public class ServiceDefinitionMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
private List<ServiceDefinition> serviceDefinitions = new LinkedList<>();
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
if (roundEnv.processingOver()) {
ClassPathMetadataStorage writer = new ClassPathMetadataStorage(processingEnv);
writer.write(() -> new Gson().toJson(serviceDefinitions), "META-INF/dubbo/service-definitions.json");
}
return false;
}
private void process(ProcessingEnvironment processingEnv, TypeElement serviceType, Set<? extends TypeElement> annotations) {
serviceDefinitions.add(build(processingEnv, serviceType));
}
}

View File

@ -1,50 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeMirror;
import java.lang.reflect.Array;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
/**
* {@link TypeDefinitionBuilder} for Java {@link Array}
*
* @since 2.7.5
*/
public class ArrayTypeDefinitionBuilder implements TypeDefinitionBuilder<ArrayType> {
@Override
public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
return isArrayType(type);
}
@Override
public void build(ProcessingEnvironment processingEnv, ArrayType type, TypeDefinition typeDefinition) {
TypeMirror componentType = type.getComponentType();
typeDefinition.getItems().add(TypeDefinitionBuilder.build(processingEnv, componentType));
}
@Override
public int getPriority() {
return MIN_PRIORITY - 4;
}
}

View File

@ -1,61 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.Collection;
import java.util.Objects;
/**
* {@link TypeDefinitionBuilder} for Java {@link Collection}
*
* @since 2.7.5
*/
public class CollectionTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
@Override
public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
Elements elements = processingEnv.getElementUtils();
TypeElement collectionTypeElement = elements.getTypeElement(Collection.class.getTypeName());
TypeMirror collectionType = collectionTypeElement.asType();
Types types = processingEnv.getTypeUtils();
TypeMirror erasedType = types.erasure(type);
return types.isAssignable(erasedType, collectionType);
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
// Generic Type arguments
type.getTypeArguments()
.stream()
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
.filter(Objects::nonNull)
.forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
}
@Override
public int getPriority() {
return MIN_PRIORITY - 5;
}
}

View File

@ -1,49 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
/**
* An interface of {@link TypeDefinitionBuilder} for {@link DeclaredType}
*
* @since 2.7.5
*/
public interface DeclaredTypeDefinitionBuilder extends TypeDefinitionBuilder<DeclaredType> {
@Override
default boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
DeclaredType declaredType = ofDeclaredType(type);
if (declaredType == null) {
return false;
}
return accept(processingEnv, declaredType);
}
/**
* Test the specified {@link DeclaredType type} is accepted or not
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link DeclaredType type}
* @return <code>true</code> if accepted
*/
boolean accept(ProcessingEnvironment processingEnv, DeclaredType type);
}

View File

@ -1,55 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.annotation.processing.util.FieldUtils;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.type.DeclaredType;
import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
/**
* {@link TypeDefinitionBuilder} for Java {@link Enum}
*
* @since 2.7.5
*/
public class EnumTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
@Override
public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
return isEnumType(type);
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
getDeclaredFields(type, FieldUtils::isEnumMemberField)
.stream()
.map(Element::getSimpleName)
.map(Name::toString)
.forEach(typeDefinition.getEnums()::add);
}
@Override
public int getPriority() {
return MIN_PRIORITY - 2;
}
}

View File

@ -1,65 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
/**
* {@link TypeDefinitionBuilder} for General Object
*
* @since 2.7.5
*/
public class GeneralTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
@Override
public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
return isClassType(type);
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
String typeName = type.toString();
TypeElement typeElement = getType(processingEnv, typeName);
buildProperties(processingEnv, typeElement, typeDefinition);
}
protected void buildProperties(ProcessingEnvironment processingEnv, TypeElement type, TypeDefinition definition) {
getNonStaticFields(type).forEach(field -> {
String fieldName = field.getSimpleName().toString();
TypeDefinition propertyType = TypeDefinitionBuilder.build(processingEnv, field);
if (propertyType != null) {
definition.getProperties().put(fieldName, propertyType);
}
});
}
@Override
public int getPriority() {
return MIN_PRIORITY;
}
}

View File

@ -1,62 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.Map;
import java.util.Objects;
/**
* {@link TypeDefinitionBuilder} for Java {@link Map}
*
* @since 2.7.5
*/
public class MapTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
@Override
public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
Elements elements = processingEnv.getElementUtils();
TypeElement mapTypeElement = elements.getTypeElement(Map.class.getTypeName());
TypeMirror mapType = mapTypeElement.asType();
Types types = processingEnv.getTypeUtils();
TypeMirror erasedType = types.erasure(type);
return types.isAssignable(erasedType, mapType);
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
// Generic Type arguments
type.getTypeArguments()
.stream()
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
.filter(Objects::nonNull)
.forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
}
@Override
public int getPriority() {
return MIN_PRIORITY - 6;
}
}

View File

@ -1,53 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.stream.Collectors;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodParameterTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getReturnType;
/**
* A Builder class for {@link MethodDefinition}
*
* @see MethodDefinition
* @since 2.7.5
*/
public interface MethodDefinitionBuilder {
static MethodDefinition build(ProcessingEnvironment processingEnv, ExecutableElement method) {
MethodDefinition methodDefinition = new MethodDefinition();
methodDefinition.setName(getMethodName(method));
methodDefinition.setReturnType(getReturnType(method));
methodDefinition.setParameterTypes(getMethodParameterTypes(method));
methodDefinition.setParameters(getMethodParameters(processingEnv, method));
return methodDefinition;
}
static List<TypeDefinition> getMethodParameters(ProcessingEnvironment processingEnv, ExecutableElement method) {
return method.getParameters().stream()
.map(element -> TypeDefinitionBuilder.build(processingEnv, element))
.collect(Collectors.toList());
}
}

View File

@ -1,48 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeMirror;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
/**
* {@link TypeDefinitionBuilder} for Java {@link PrimitiveType primitve type}
*
* @since 2.7.5
*/
public class PrimitiveTypeDefinitionBuilder implements TypeDefinitionBuilder<PrimitiveType> {
@Override
public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
return isPrimitiveType(type);
}
@Override
public void build(ProcessingEnvironment processingEnv, PrimitiveType type, TypeDefinition typeDefinition) {
// DO NOTHING
}
@Override
public int getPriority() {
return MIN_PRIORITY - 3;
}
}

View File

@ -1,56 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
/**
* A Builder for {@link ServiceDefinition}
*
* @see ServiceDefinition
* @since 2.7.5
*/
public interface ServiceDefinitionBuilder {
static ServiceDefinition build(ProcessingEnvironment processingEnv, TypeElement type) {
ServiceDefinition serviceDefinition = new ServiceDefinition();
serviceDefinition.setCanonicalName(type.toString());
serviceDefinition.setCodeSource(getResourceName(type.toString()));
// Get all super types and interface excluding the specified type
// and then the result will be added into ServiceDefinition#getTypes()
getHierarchicalTypes(type.asType(), Object.class)
.stream()
.map(t -> TypeDefinitionBuilder.build(processingEnv, t))
.forEach(serviceDefinition.getTypes()::add);
// Get all declared methods that will be added into ServiceDefinition#getMethods()
getPublicNonStaticMethods(type, Object.class)
.stream()
.map(method -> MethodDefinitionBuilder.build(processingEnv, method))
.forEach(serviceDefinition.getMethods()::add);
return serviceDefinition;
}
}

View File

@ -1,49 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.annotation.processing.util.TypeUtils;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.DeclaredType;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
/**
* {@link TypeDefinitionBuilder} for {@link TypeUtils#SIMPLE_TYPES Java Simple Type}
*
* @since 2.7.5
*/
public class SimpleTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
@Override
public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
return isSimpleType(type);
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
// DO NOTHING
}
@Override
public int getPriority() {
return MIN_PRIORITY - 1;
}
}

View File

@ -1,95 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
* A class builds the instance of {@link TypeDefinition}
*
* @since 2.7.5
*/
@SPI
public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized {
/**
* Test the specified {@link TypeMirror type} is accepted or not
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link TypeMirror type}
* @return <code>true</code> if accepted
*/
boolean accept(ProcessingEnvironment processingEnv, TypeMirror type);
/**
* Build the instance of {@link TypeDefinition}
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link T type}
* @param typeDefinition {@link TypeDefinition} to be built
* @return an instance of {@link TypeDefinition}
*/
void build(ProcessingEnvironment processingEnv, T type, TypeDefinition typeDefinition);
/**
* Build the instance of {@link TypeDefinition} from the specified {@link Element element}
*
* @param processingEnv {@link ProcessingEnvironment}
* @param element {@link Element source element}
* @return non-null
*/
static TypeDefinition build(ProcessingEnvironment processingEnv, Element element) {
TypeDefinition typeDefinition = build(processingEnv, element.asType());
typeDefinition.set$ref(element.toString());
return typeDefinition;
}
/**
* Build the instance of {@link TypeDefinition} from the specified {@link TypeMirror type}
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link TypeMirror type}
* @return non-null
*/
static TypeDefinition build(ProcessingEnvironment processingEnv, TypeMirror type) {
String typeName = type.toString();
TypeDefinition typeDefinition = new TypeDefinition(typeName);
// Build by all instances of TypeDefinitionBuilder that were loaded By Java SPI
// load(TypeDefinitionBuilder.class, TypeDefinitionBuilder.class.getClassLoader())
getExtensionLoader(TypeDefinitionBuilder.class)
.getSupportedExtensionInstances()
.stream()
.filter(builder -> builder.accept(processingEnv, type))
.findFirst()
.ifPresent(builder -> {
builder.build(processingEnv, type, typeDefinition);
// typeDefinition.setTypeBuilderName(builder.getClass().getName());
});
return typeDefinition;
}
}

View File

@ -1,52 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
/**
* The abstract {@link AnnotatedMethodParameterProcessor} implementation
*
* @since 2.7.5
*/
public abstract class AbstractAnnotatedMethodParameterProcessor implements AnnotatedMethodParameterProcessor {
@Override
public final void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
String annotationValue = getAnnotationValue(annotation, parameter, parameterIndex);
String defaultValue = getDefaultValue(annotation, parameter, parameterIndex);
process(annotationValue, defaultValue, annotation, parameter, parameterIndex, method, restMethodMetadata);
}
protected abstract void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
ExecutableElement method, RestMethodMetadata restMethodMetadata);
protected String getAnnotationValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
return getValue(annotation);
}
protected String getDefaultValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
return buildDefaultValue(parameterIndex);
}
}

View File

@ -1,234 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import org.apache.dubbo.metadata.rest.RequestMetadata;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.lang.ThreadLocal.withInitial;
import static java.util.Collections.emptyList;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.metadata.annotation.processing.builder.MethodDefinitionBuilder.build;
import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getGroup;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getVersion;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.resolveServiceInterfaceName;
/**
* Abstract {@link ServiceRestMetadataProcessor} implementation
*
* @since 2.7.5
*/
public abstract class AbstractServiceRestMetadataProcessor implements ServiceRestMetadataProcessor {
private final static ThreadLocal<Map<String, Object>> threadLocalCache = withInitial(HashMap::new);
private final static Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = loadAnnotatedMethodParameterProcessors();
private final String processorName = getClass().getSimpleName();
@Override
public final ServiceRestMetadata process(ProcessingEnvironment processingEnv,
TypeElement serviceType,
Set<? extends TypeElement> annotations) {
info("%s is processing the service type[%s] with annotations[%s]", processorName, serviceType,
annotations.stream().map(t -> "@" + t.toString()).collect(Collectors.joining(",")));
ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata();
try {
AnnotationMirror serviceAnnotation = getAnnotation(serviceType);
serviceRestMetadata.setServiceInterface(resolveServiceInterfaceName(serviceType, serviceAnnotation));
serviceRestMetadata.setGroup(getGroup(serviceAnnotation));
serviceRestMetadata.setVersion(getVersion(serviceAnnotation));
List<? extends ExecutableElement> methods = getPublicNonStaticMethods(serviceType, Object.class);
methods.forEach(method -> {
processRestMethodMetadata(processingEnv, serviceType, method)
.ifPresent(serviceRestMetadata.getMeta()::add);
});
} finally {
clearCache();
}
info("The %s's process result : %s", processorName, serviceRestMetadata);
return serviceRestMetadata;
}
protected Optional<RestMethodMetadata> processRestMethodMetadata(ProcessingEnvironment processingEnv,
TypeElement serviceType, ExecutableElement method) {
String requestPath = getRequestPath(processingEnv, serviceType, method); // requestPath is required
if (requestPath == null) {
return empty();
}
String requestMethod = getRequestMethod(processingEnv, serviceType, method); // requestMethod is required
if (requestMethod == null) {
return empty();
}
RestMethodMetadata metadata = new RestMethodMetadata();
MethodDefinition methodDefinition = getMethodDefinition(processingEnv, serviceType, method);
// Set MethodDefinition
metadata.setMethod(methodDefinition);
// process the annotated method parameters
processAnnotatedMethodParameters(method, serviceType, metadata);
// process produces
Set<String> produces = new LinkedHashSet<>();
processProduces(processingEnv, serviceType, method, produces);
// process consumes
Set<String> consumes = new LinkedHashSet<>();
processConsumes(processingEnv, serviceType, method, consumes);
// Initialize RequestMetadata
RequestMetadata request = metadata.getRequest();
request.setPath(requestPath);
request.setMethod(requestMethod);
request.setProduces(produces);
request.setConsumes(consumes);
// Post-Process
postProcessRestMethodMetadata(processingEnv, serviceType, method, metadata);
return of(metadata);
}
/**
* Post-Process for {@link RestMethodMetadata}, sub-type could override this method for further works
*
* @param processingEnv {@link ProcessingEnvironment}
* @param serviceType The type that @Service annotated
* @param method The public method of <code>serviceType</code>
* @param metadata {@link RestMethodMetadata} maybe updated
*/
protected void postProcessRestMethodMetadata(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, RestMethodMetadata metadata) {
}
protected abstract String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method);
protected abstract String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method);
protected MethodDefinition getMethodDefinition(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
return build(processingEnv, method);
}
protected void processAnnotatedMethodParameters(ExecutableElement method, TypeElement type,
RestMethodMetadata metadata) {
List<? extends VariableElement> methodParameters = method.getParameters();
int size = methodParameters.size();
for (int i = 0; i < size; i++) {
VariableElement parameter = methodParameters.get(i);
// Add indexed parameter name
metadata.addIndexToName(i, parameter.getSimpleName().toString());
processAnnotatedMethodParameter(parameter, i, method, type, metadata);
}
}
protected void processAnnotatedMethodParameter(VariableElement parameter, int parameterIndex,
ExecutableElement method, TypeElement serviceType,
RestMethodMetadata metadata) {
parameter.getAnnotationMirrors().forEach(annotation -> {
String annotationType = annotation.getAnnotationType().toString();
parameterProcessorsMap.getOrDefault(annotationType, emptyList())
.forEach(parameterProcessor -> {
parameterProcessor.process(annotation, parameter, parameterIndex, method, metadata);
});
});
}
protected abstract void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> produces);
protected abstract void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> consumes);
protected static final void put(String name, Object value) {
Map<String, Object> cache = getCache();
cache.put(name, value);
}
protected static final <T> T get(String name) throws ClassCastException {
Map<String, Object> cache = getCache();
return (T) cache.get(name);
}
protected static final <V> V computeIfAbsent(String name, Function<? super String, ? extends V> mappingFunction) {
return (V) getCache().computeIfAbsent(name, mappingFunction);
}
private static Map<String, List<AnnotatedMethodParameterProcessor>> loadAnnotatedMethodParameterProcessors() {
Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = new LinkedHashMap<>();
// load(AnnotatedMethodParameterProcessor.class, AnnotatedMethodParameterProcessor.class.getClassLoader())
getExtensionLoader(AnnotatedMethodParameterProcessor.class)
.getSupportedExtensionInstances()
.forEach(processor -> {
List<AnnotatedMethodParameterProcessor> processors =
parameterProcessorsMap.computeIfAbsent(processor.getAnnotationType(), k -> new LinkedList<>());
processors.add(processor);
});
return parameterProcessorsMap;
}
private static Map<String, Object> getCache() {
return threadLocalCache.get();
}
private static void clearCache() {
Map<String, Object> cache = getCache();
cache.clear();
threadLocalCache.remove();
}
}

View File

@ -1,64 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
/**
* The interface to process the parameter of method that was annotated
*
* @since 2.7.5
*/
@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 AnnotationMirror the target annotation} whose type is {@link #getAnnotationType()}
* @param parameter {@link VariableElement method parameter}
* @param parameterIndex the index of parameter in the method
* @param method {@link ExecutableElement method that parameter belongs to}
* @param restMethodMetadata {@link RestMethodMetadata the metadata is used to update}
*/
void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method,
RestMethodMetadata restMethodMetadata);
/**
* Build the default value
*
* @param parameterIndex the index of parameter
* @return the placeholder
*/
static String buildDefaultValue(int parameterIndex) {
return "{" + parameterIndex + "}";
}
}

View File

@ -1,59 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import java.util.Set;
/**
* The default implementation of {@link ServiceRestMetadataProcessor}
*
* @since 2.7.5
*/
public class DefaultServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
@Override
public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
return true;
}
@Override
protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
return null;
}
@Override
protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
return null;
}
@Override
protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> produces) {
}
@Override
protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> consumes) {
}
}

View File

@ -1,88 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.metadata.annotation.processing.AbstractServiceAnnotationProcessor;
import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.TypeElement;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static javax.lang.model.util.ElementFilter.typesIn;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.isServiceAnnotationPresent;
/**
* The {@link Processor} class to generate the metadata of REST from the classes that are annotated by Dubbo's
*
* @Service
* @see Processor
* @since 2.7.5
*/
public class ServiceRestMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
private List<ServiceRestMetadataProcessor> metadataProcessors;
private ServiceRestMetadataStorage serviceRestMetadataWriter;
private Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.metadataProcessors = new LinkedList<>(getExtensionLoader(ServiceRestMetadataProcessor.class).getSupportedExtensionInstances());
this.serviceRestMetadataWriter = new ServiceRestMetadataStorage(processingEnv);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
if (roundEnv.processingOver()) {
try {
serviceRestMetadataWriter.append(serviceRestMetadata);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
return false;
}
private void process(ProcessingEnvironment processingEnv, TypeElement serviceType,
Set<? extends TypeElement> annotations) {
metadataProcessors
.stream()
.filter(processor -> supports(processor, processingEnv, serviceType))
.map(processor -> processor.process(processingEnv, serviceType, annotations))
.forEach(serviceRestMetadata::add);
}
private boolean supports(ServiceRestMetadataProcessor processor, ProcessingEnvironment processingEnv,
TypeElement serviceType) {
// @Service must be present in service type
return isServiceAnnotationPresent(serviceType) && processor.supports(processingEnv, serviceType);
}
}

View File

@ -1,55 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import java.util.Set;
/**
* The class to process {@link ServiceRestMetadata} based on Annotation Processor Tool
*
* @since 2.7.5
*/
@SPI
public interface ServiceRestMetadataProcessor extends Prioritized {
/**
* Supports or not to the specified service type
*
* @param processingEnvironment {@link ProcessingEnvironment}
* @param serviceType Dubbo service type or interface
* @return if supports, return <code>true</code>, or <code>false</code>
*/
boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType);
/**
* Process the {@link ServiceRestMetadata} from given service type
*
* @param processingEnvironment {@link ProcessingEnvironment}
* @param serviceType Dubbo service type or interface
* @param annotations
* @return non-null
*/
ServiceRestMetadata process(ProcessingEnvironment processingEnvironment,
TypeElement serviceType,
Set<? extends TypeElement> annotations);
}

View File

@ -1,66 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest;
import org.apache.dubbo.metadata.annotation.processing.ClassPathMetadataStorage;
import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
import com.google.gson.Gson;
import javax.annotation.processing.ProcessingEnvironment;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static com.google.gson.reflect.TypeToken.getParameterized;
/**
* The storage for {@link ServiceRestMetadata}
*/
public class ServiceRestMetadataStorage {
public static final String METADATA_RESOURCE_PATH = "META-INF/dubbo/service-rest-metadata.json";
private final ClassPathMetadataStorage storage;
public ServiceRestMetadataStorage(ProcessingEnvironment processingEnv) {
this.storage = new ClassPathMetadataStorage(processingEnv);
}
public void append(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
Set<ServiceRestMetadata> allServiceRestMetadata = new LinkedHashSet<>();
storage.read(METADATA_RESOURCE_PATH, reader -> {
Gson gson = new Gson();
return (List) gson.fromJson(reader, getParameterized(List.class, ServiceRestMetadata.class).getType());
}).ifPresent(existedMetadata -> {
// Add all existed ServiceRestMetadata
allServiceRestMetadata.addAll(existedMetadata);
});
// Add all new ServiceRestMetadata
allServiceRestMetadata.addAll(serviceRestMetadata);
write(serviceRestMetadata);
}
public void write(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
if (serviceRestMetadata.isEmpty()) {
return;
}
storage.write(() -> new Gson().toJson(serviceRestMetadata), METADATA_RESOURCE_PATH);
}
}

View File

@ -1,78 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RequestMetadata;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import java.util.List;
import java.util.Map;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @DefaultValue
* *
*
* @since 2.7.5
*/
public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
/**
* The annotation class name of @DefaultValue
*/
public static final String DEFAULT_VALUE_ANNOTATION_CLASS_NAME = "javax.ws.rs.DefaultValue";
@Override
public String getAnnotationType() {
return DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
}
@Override
protected void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
// process the request parameters
setDefaultValue(requestMetadata.getParams(), defaultValue, annotationValue);
// process the request headers
setDefaultValue(requestMetadata.getHeaders(), defaultValue, annotationValue);
}
private void setDefaultValue(Map<String, List<String>> source, String placeholderValue, String defaultValue) {
OUTTER:
for (Map.Entry<String, List<String>> entry : source.entrySet()) {
List<String> values = entry.getValue();
int size = values.size();
for (int i = 0; i < size; i++) {
String value = values.get(i);
if (placeholderValue.equals(value)) {
values.set(i, defaultValue);
break OUTTER;
}
}
}
}
public int getPriority() {
return MIN_PRIORITY;
}
}

View File

@ -1,50 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RequestMetadata;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @HeaderParam
*
* @since 2.7.5
*/
public class HeaderParamParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
@Override
public String getAnnotationType() {
return "javax.ws.rs.HeaderParam";
}
@Override
protected void process(String headerName, String defaultValue, AnnotationMirror annotation,
VariableElement parameter, int parameterIndex,
ExecutableElement method, RestMethodMetadata restMethodMetadata) {
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
// Add the placeholder as header value
requestMetadata.addHeader(headerName, buildDefaultValue(parameterIndex));
}
}

View File

@ -1,113 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import java.util.Set;
import java.util.stream.Stream;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
/**
* {@link ServiceRestMetadataProcessor} implementation for JAX-RS 2 and 1
*
* @since 2.7.5
*/
public class JAXRSServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
/**
* The annotation name of @Path
*/
public static final String PATH_ANNOTATION_CLASS_NAME = "javax.ws.rs.Path";
/**
* The annotation name of @HttpMethod
*/
public static final String HTTP_METHOD_ANNOTATION_CLASS_NAME = "javax.ws.rs.HttpMethod";
/**
* The annotation class name of @Produces
*/
public static final String PRODUCES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Produces";
/**
* The annotation class name of @Consumes
*/
public static final String CONSUMES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Consumes";
@Override
public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
}
@Override
protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
String pathFromType = getPathValue(processingEnv, serviceType);
String pathFromMethod = getPathValue(method);
return buildPath(pathFromType, pathFromMethod);
}
@Override
protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
AnnotationMirror annotation = findMetaAnnotation(method, HTTP_METHOD_ANNOTATION_CLASS_NAME);
return getValue(annotation);
}
@Override
protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> produces) {
addAnnotationValues(method, PRODUCES_ANNOTATION_CLASS_NAME, produces);
}
@Override
protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> consumes) {
addAnnotationValues(method, CONSUMES_ANNOTATION_CLASS_NAME, consumes);
}
private void addAnnotationValues(Element element, String annotationAttributeName, Set<String> result) {
AnnotationMirror annotation = findAnnotation(element, annotationAttributeName);
String[] value = getValue(annotation);
if (value != null) {
Stream.of(value).forEach(result::add);
}
}
private String getPathValue(ProcessingEnvironment processingEnv, TypeElement serviceType) {
AnnotationMirror annotation = findAnnotation(serviceType, PATH_ANNOTATION_CLASS_NAME);
return getValue(annotation);
}
private String getPathValue(AnnotatedConstruct annotatedConstruct) {
AnnotationMirror annotation = getAnnotation(annotatedConstruct, PATH_ANNOTATION_CLASS_NAME);
return getValue(annotation);
}
}

View File

@ -1,32 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @MatrixParam
*
* @since 2.7.5
*/
public class MatrixParamParameterProcessor extends ParamAnnotationParameterProcessor {
@Override
public String getAnnotationType() {
return "javax.ws.rs.MatrixParam";
}
}

View File

@ -1,38 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RequestMetadata;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
/**
* The abstract {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @*Param
*/
public abstract class ParamAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
ExecutableElement method, RestMethodMetadata restMethodMetadata) {
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
requestMetadata.addParam(name, defaultValue);
}
}

View File

@ -1,32 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @QueryParam
*
* @since 2.7.5
*/
public class QueryParamParameterProcessor extends ParamAnnotationParameterProcessor {
@Override
public String getAnnotationType() {
return "javax.ws.rs.QueryParam";
}
}

View File

@ -1,69 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
/**
* The abstract {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @Request*
*/
public abstract class AbstractRequestAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
protected abstract void process(String name, String defaultValue, AnnotationMirror annotation,
VariableElement parameter, int parameterIndex,
ExecutableElement method,
RestMethodMetadata restMethodMetadata);
@Override
protected String getAnnotationValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
// try to get "value" attribute first
String name = super.getAnnotationValue(annotation, parameter, parameterIndex);
// try to get "name" attribute if required
if (isEmpty(name)) {
name = getAttribute(annotation, "name");
}
// finally , try to the name of parameter
if (isEmpty(name)) {
name = parameter.getSimpleName().toString();
}
return name;
}
protected String getDefaultValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
String defaultValue = getAttribute(annotation, "defaultValue");
if (isEmpty(defaultValue)) {
defaultValue = super.getDefaultValue(annotation, parameter, parameterIndex);
}
return defaultValue;
}
protected boolean isEmpty(String str) {
return str == null || str.isEmpty();
}
}

View File

@ -1,41 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestHeader
*/
public class RequestHeaderParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
@Override
public String getAnnotationType() {
return "org.springframework.web.bind.annotation.RequestHeader";
}
@Override
protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
restMethodMetadata.getRequest().addHeader(name, defaultValue);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
import org.apache.dubbo.metadata.rest.RestMethodMetadata;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
/**
* The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestParam
*/
@SPI
public class RequestParamParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
@Override
public String getAnnotationType() {
return "org.springframework.web.bind.annotation.RequestParam";
}
@Override
protected void process(String name, String defaultValue, AnnotationMirror annotation,
VariableElement parameter, int parameterIndex,
ExecutableElement method, RestMethodMetadata restMethodMetadata) {
restMethodMetadata.getRequest().addParam(name, defaultValue);
}
}

View File

@ -1,157 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import java.lang.reflect.Array;
import java.util.Set;
import static java.lang.String.valueOf;
import static java.lang.reflect.Array.getLength;
import static java.util.stream.Stream.of;
import static org.apache.dubbo.common.function.Streams.filterFirst;
import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAllAnnotations;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
/**
* {@link ServiceRestMetadataProcessor}
*
* @since 2.7.5
*/
public class SpringMvcServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
private static final int FIRST_ELEMENT_INDEX = 0;
public static final String CONTROLLER_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Controller";
public static final String REQUEST_MAPPING_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestMapping";
@Override
public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
}
@Override
protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
String requestPathFromType = getRequestPath(serviceType);
String requestPathFromMethod = getRequestPath(method);
return buildPath(requestPathFromType, requestPathFromMethod);
}
@Override
protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
AnnotationMirror requestMapping = getRequestMapping(method);
// httpMethod is an array of RequestMethod
Object httpMethod = getAttribute(requestMapping, "method");
if (httpMethod == null || getLength(httpMethod) < 1) {
return null;
}
// TODO Is is required to support more request methods?
return valueOf(Array.get(httpMethod, FIRST_ELEMENT_INDEX));
}
private AnnotationMirror getRequestMapping(Element element) {
// try "@RequestMapping" first
AnnotationMirror requestMapping = findAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
// try the annotation meta-annotated later
if (requestMapping == null) {
requestMapping = findMetaAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
}
return requestMapping;
}
@Override
protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> produces) {
addMediaTypes(method, "produces", produces);
}
@Override
protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method, Set<String> consumes) {
addMediaTypes(method, "consumes", consumes);
}
private void addMediaTypes(ExecutableElement method, String annotationAttributeName, Set<String> mediaTypesSet) {
AnnotationMirror mappingAnnotation = getMappingAnnotation(method);
String[] mediaTypes = getAttribute(mappingAnnotation, annotationAttributeName);
if (isNotEmpty(mediaTypes)) {
of(mediaTypes).forEach(mediaTypesSet::add);
}
}
private AnnotationMirror getMappingAnnotation(Element element) {
return computeIfAbsent(valueOf(element), key ->
filterFirst(getAllAnnotations(element), annotation -> {
DeclaredType annotationType = annotation.getAnnotationType();
// try "@RequestMapping" first
if (REQUEST_MAPPING_ANNOTATION_CLASS_NAME.equals(annotationType.toString())) {
return true;
}
// try meta annotation
return isAnnotationPresent(annotationType.asElement(), REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
})
);
}
private String getRequestPath(Element element) {
AnnotationMirror mappingAnnotation = getMappingAnnotation(element);
return getRequestPath(mappingAnnotation);
}
private String getRequestPath(AnnotationMirror mappingAnnotation) {
// try "value" first
String[] value = getAttribute(mappingAnnotation, "value");
if (isEmpty(value)) { // try "path" later
value = getAttribute(mappingAnnotation, "path");
}
if (isEmpty(value)) {
return "";
}
// TODO Is is required to support more request paths?
return value[FIRST_ELEMENT_INDEX];
}
}

View File

@ -1,233 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.util;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeMirror;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.lang.Enum.valueOf;
import static java.util.Collections.emptyList;
import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
import static org.apache.dubbo.common.function.Streams.filterAll;
import static org.apache.dubbo.common.function.Streams.filterFirst;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSameType;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isTypeElement;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
/**
* The utilities class for annotation in the package "javax.lang.model.*"
*
* @since 2.7.5
*/
public interface AnnotationUtils {
static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct,
Class<? extends Annotation> annotationClass) {
return annotationClass == null ?
null :
getAnnotation(annotatedConstruct, annotationClass.getTypeName());
}
static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) {
List<AnnotationMirror> annotations = getAnnotations(annotatedConstruct, annotationClassName);
return annotations.isEmpty() ? null : annotations.get(0);
}
static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct, Class<? extends Annotation> annotationClass) {
return annotationClass == null ?
emptyList() :
getAnnotations(annotatedConstruct, annotationClass.getTypeName());
}
static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
CharSequence annotationClassName) {
return getAnnotations(annotatedConstruct,
annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
}
static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct) {
return getAnnotations(annotatedConstruct, EMPTY_ARRAY);
}
static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
Predicate<AnnotationMirror>... annotationFilters) {
AnnotatedConstruct actualAnnotatedConstruct = annotatedConstruct;
if (annotatedConstruct instanceof TypeMirror) {
actualAnnotatedConstruct = ofTypeElement((TypeMirror) actualAnnotatedConstruct);
}
return actualAnnotatedConstruct == null ?
emptyList() :
filterAll((List<AnnotationMirror>) actualAnnotatedConstruct.getAnnotationMirrors(), annotationFilters);
}
static List<AnnotationMirror> getAllAnnotations(TypeMirror type) {
return getAllAnnotations(ofTypeElement(type));
}
static List<AnnotationMirror> getAllAnnotations(Element element) {
return getAllAnnotations(element, EMPTY_ARRAY);
}
static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Class<? extends Annotation> annotationClass) {
return getAllAnnotations(ofTypeElement(type), annotationClass);
}
static List<AnnotationMirror> getAllAnnotations(Element element, Class<? extends Annotation> annotationClass) {
return element == null || annotationClass == null ?
emptyList() :
getAllAnnotations(element, annotationClass.getTypeName());
}
static List<AnnotationMirror> getAllAnnotations(TypeMirror type, CharSequence annotationClassName) {
return getAllAnnotations(ofTypeElement(type), annotationClassName);
}
static List<AnnotationMirror> getAllAnnotations(Element element, CharSequence annotationClassName) {
return getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
}
static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Predicate<AnnotationMirror>... annotationFilters) {
return getAllAnnotations(ofTypeElement(type), annotationFilters);
}
static List<AnnotationMirror> getAllAnnotations(Element element, Predicate<AnnotationMirror>... annotationFilters) {
List<AnnotationMirror> allAnnotations = isTypeElement(element) ?
getHierarchicalTypes(ofTypeElement(element))
.stream()
.map(AnnotationUtils::getAnnotations)
.flatMap(Collection::stream)
.collect(Collectors.toList()) :
element == null ? emptyList() : (List<AnnotationMirror>) element.getAnnotationMirrors();
return filterAll(allAnnotations, annotationFilters);
}
static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType) {
return getAllAnnotations(processingEnv, annotatedType, EMPTY_ARRAY);
}
static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType,
Predicate<AnnotationMirror>... annotationFilters) {
return annotatedType == null ?
emptyList() :
getAllAnnotations(processingEnv, annotatedType.getTypeName(), annotationFilters);
}
static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, CharSequence annotatedTypeName,
Predicate<AnnotationMirror>... annotationFilters) {
return getAllAnnotations(getType(processingEnv, annotatedTypeName), annotationFilters);
}
static AnnotationMirror findAnnotation(TypeMirror type, Class<? extends Annotation> annotationClass) {
return annotationClass == null ? null : findAnnotation(type, annotationClass.getTypeName());
}
static AnnotationMirror findAnnotation(TypeMirror type, CharSequence annotationClassName) {
return findAnnotation(ofTypeElement(type), annotationClassName);
}
static AnnotationMirror findAnnotation(Element element, Class<? extends Annotation> annotationClass) {
return annotationClass == null ? null : findAnnotation(element, annotationClass.getTypeName());
}
static AnnotationMirror findAnnotation(Element element, CharSequence annotationClassName) {
return filterFirst(getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName)));
}
static AnnotationMirror findMetaAnnotation(Element annotatedConstruct, CharSequence metaAnnotationClassName) {
return annotatedConstruct == null ?
null :
getAnnotations(annotatedConstruct)
.stream()
.map(annotation -> findAnnotation(annotation.getAnnotationType(), metaAnnotationClassName))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
static boolean isAnnotationPresent(Element element, CharSequence annotationClassName) {
return findAnnotation(element, annotationClassName) != null ||
findMetaAnnotation(element, annotationClassName) != null;
}
static <T> T getAttribute(AnnotationMirror annotation, String attributeName) {
return annotation == null ? null : getAttribute(annotation.getElementValues(), attributeName);
}
static <T> T getAttribute(Map<? extends ExecutableElement, ? extends AnnotationValue> attributesMap,
String attributeName) {
T annotationValue = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : attributesMap.entrySet()) {
ExecutableElement attributeMethod = entry.getKey();
if (Objects.equals(attributeName, attributeMethod.getSimpleName().toString())) {
TypeMirror attributeType = attributeMethod.getReturnType();
AnnotationValue value = entry.getValue();
if (attributeType instanceof ArrayType) { // array-typed attribute values
ArrayType arrayType = (ArrayType) attributeType;
String componentType = arrayType.getComponentType().toString();
ClassLoader classLoader = AnnotationUtils.class.getClassLoader();
List<AnnotationValue> values = (List<AnnotationValue>) value.getValue();
int size = values.size();
try {
Class componentClass = classLoader.loadClass(componentType);
boolean isEnum = componentClass.isEnum();
Object array = Array.newInstance(componentClass, values.size());
for (int i = 0; i < size; i++) {
Object element = values.get(i).getValue();
if (isEnum) {
element = valueOf(componentClass, element.toString());
}
Array.set(array, i, element);
}
annotationValue = (T) array;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
annotationValue = (T) value.getValue();
}
break;
}
}
return annotationValue;
}
static <T> T getValue(AnnotationMirror annotation) {
return (T) getAttribute(annotation, "value");
}
}

View File

@ -1,146 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.util;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static javax.lang.model.element.ElementKind.ENUM_CONSTANT;
import static javax.lang.model.element.ElementKind.FIELD;
import static javax.lang.model.element.Modifier.STATIC;
import static javax.lang.model.util.ElementFilter.fieldsIn;
import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
import static org.apache.dubbo.common.function.Streams.filterAll;
import static org.apache.dubbo.common.function.Streams.filterFirst;
import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.hasModifiers;
import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matches;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
/**
* The utilities class for the field in the package "javax.lang.model."
*
* @since 2.7.5
*/
public interface FieldUtils {
static List<VariableElement> getDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
return element == null ? emptyList() : getDeclaredFields(element.asType(), fieldFilters);
}
static List<VariableElement> getDeclaredFields(Element element) {
return getDeclaredFields(element, EMPTY_ARRAY);
}
static List<VariableElement> getDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
return filterAll(fieldsIn(getDeclaredMembers(type)), fieldFilters);
}
static List<VariableElement> getDeclaredFields(TypeMirror type) {
return getDeclaredFields(type, EMPTY_ARRAY);
}
static List<VariableElement> getAllDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
return element == null ? emptyList() : getAllDeclaredFields(element.asType(), fieldFilters);
}
static List<VariableElement> getAllDeclaredFields(Element element) {
return getAllDeclaredFields(element, EMPTY_ARRAY);
}
static List<VariableElement> getAllDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
return getHierarchicalTypes(type)
.stream()
.map(t -> getDeclaredFields(t, fieldFilters))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
static List<VariableElement> getAllDeclaredFields(TypeMirror type) {
return getAllDeclaredFields(type, EMPTY_ARRAY);
}
static VariableElement getDeclaredField(Element element, String fieldName) {
return element == null ? null : getDeclaredField(element.asType(), fieldName);
}
static VariableElement getDeclaredField(TypeMirror type, String fieldName) {
return filterFirst(getDeclaredFields(type, field -> fieldName.equals(field.getSimpleName().toString())));
}
static VariableElement findField(Element element, String fieldName) {
return element == null ? null : findField(element.asType(), fieldName);
}
static VariableElement findField(TypeMirror type, String fieldName) {
return filterFirst(getAllDeclaredFields(type, field -> equals(field, fieldName)));
}
/**
* is Enum's member field or not
*
* @param field {@link VariableElement} must be public static final fields
* @return if field is public static final, return <code>true</code>, or <code>false</code>
*/
static boolean isEnumMemberField(VariableElement field) {
if (field == null || !isEnumType(field.getEnclosingElement())) {
return false;
}
return ENUM_CONSTANT.equals(field.getKind());
}
static boolean isNonStaticField(VariableElement field) {
return isField(field) && !hasModifiers(field, STATIC);
}
static boolean isField(VariableElement field) {
return matches(field, FIELD) || isEnumMemberField(field);
}
static boolean isField(VariableElement field, Modifier... modifiers) {
return isField(field) && hasModifiers(field, modifiers);
}
static List<VariableElement> getNonStaticFields(TypeMirror type) {
return getDeclaredFields(type, FieldUtils::isNonStaticField);
}
static List<VariableElement> getNonStaticFields(Element element) {
return element == null ? emptyList() : getNonStaticFields(element.asType());
}
static List<VariableElement> getAllNonStaticFields(TypeMirror type) {
return getAllDeclaredFields(type, FieldUtils::isNonStaticField);
}
static List<VariableElement> getAllNonStaticFields(Element element) {
return element == null ? emptyList() : getAllNonStaticFields(element.asType());
}
static boolean equals(VariableElement field, CharSequence fieldName) {
return field != null && fieldName != null && field.getSimpleName().toString().equals(fieldName.toString());
}
}

View File

@ -1,45 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.util;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import static java.lang.String.format;
/**
* Logger Utils
*
* @since 2.7.5
*/
public interface LoggerUtils {
Logger LOGGER = LoggerFactory.getLogger("dubbo-metadata-processor");
static void info(String format, Object... args) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info(format(format, args));
}
}
static void warn(String format, Object... args) {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn(format(format, args));
}
}
}

View File

@ -1,94 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.annotation.processing.util;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
/**
* The utilities class for the members in the package "javax.lang.model.", such as "field", "method", "constructor"
*
* @since 2.7.5
*/
public interface MemberUtils {
static boolean matches(Element member, ElementKind kind) {
return member == null || kind == null ? false : kind.equals(member.getKind());
}
static boolean isPublicNonStatic(Element member) {
return hasModifiers(member, PUBLIC) && !hasModifiers(member, STATIC);
}
static boolean hasModifiers(Element member, Modifier... modifiers) {
if (member == null || modifiers == null) {
return false;
}
Set<Modifier> actualModifiers = member.getModifiers();
for (Modifier modifier : modifiers) {
if (!actualModifiers.contains(modifier)) {
return false;
}
}
return true;
}
static List<? extends Element> getDeclaredMembers(TypeMirror type) {
TypeElement element = ofTypeElement(type);
return element == null ? emptyList() : element.getEnclosedElements();
}
static List<? extends Element> getAllDeclaredMembers(TypeMirror type) {
return getHierarchicalTypes(type)
.stream()
.map(MemberUtils::getDeclaredMembers)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
static boolean matchParameterTypes(List<? extends VariableElement> parameters, CharSequence... parameterTypes) {
int size = parameters.size();
if (size != parameterTypes.length) {
return false;
}
for (int i = 0; i < size; i++) {
VariableElement parameter = parameters.get(i);
if (!Objects.equals(parameter.asType().toString(), parameterTypes[i])) {
return false;
}
}
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More