Migrate master bugfix (#7927)

This commit is contained in:
Albumen Kevin 2021-06-01 14:14:35 +08:00 committed by GitHub
parent 4ea0a09846
commit 8bc9257f4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
327 changed files with 6310 additions and 1834 deletions

View File

@ -1,18 +1,18 @@
## Contributing to dubbo
Dubbo is released under the non-restrictive Apache 2.0 license, and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. If you want to contribute even something trivial please do not hesitate, but follow the guidelines below.
## Contributing to Dubbo
Dubbo is released under the non-restrictive Apache 2.0 licenses and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. Contributions of all form to this repository is acceptable, as long as it follows the prescribed community guidelines enumerated below.
### Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the Contributor License Agreement. Signing the contributors agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.
Before we accept a non-trivial patch or pull request (PRs), we will need you to sign the Contributor License Agreement. Signing the contributors' agreement does not grant anyone commits rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors may get invited to join the core team that will grant them privileges to merge existing PRs.
### Contact
#### Mailing list
The mailing list is the recommended way for discussing almost anything that related to Dubbo. Please refer to this [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) for detailed documentation on how to subscribe.
The mailing list is the recommended way of pursuing a discussion on almost anything related to Dubbo. Please refer to this [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) for detailed documentation on how to subscribe.
- [dev@dubbo.apache.org](mailto:dev-subscribe@dubbo.apache.org): the develop mailing list, you can ask question here if you have encountered any problem when using or developing Dubbo.
- [commits@dubbo.apache.org](mailto:commits-subscribe@dubbo.apache.org): all the commits will be sent to this mailing list. You can subscribe to it if you are interested in Dubbo's development.
- [dev@dubbo.apache.org](mailto:dev-subscribe@dubbo.apache.org): the developer mailing list where you can ask questions about an issue you may have encountered while working with Dubbo.
- [commits@dubbo.apache.org](mailto:commits-subscribe@dubbo.apache.org): the commit updates will get broadcasted on this mailing list. You can subscribe to it, should you be interested in following Dubbo's development.
- [notifications@dubbo.apache.org](mailto:notifications-subscribe@dubbo.apache.org): all the Github [issue](https://github.com/apache/dubbo/issues) updates and [pull request](https://github.com/apache/dubbo/pulls) updates will be sent to this mailing list.
### Reporting issue
@ -21,33 +21,33 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?templat
### Code Conventions
Our code style is almost in line with the standard java conventions (Popular IDE's default setting satisfy this), with the following additional restricts:
* If there are more than 120 characters in current line, start a new line.
* If there are more than 120 characters in the current line, begin a new line.
* Make sure all new .java files to have a simple Javadoc class comment with at least a @date tag identifying birth, and preferably at least a paragraph on what the class is for.
* Make sure all new .java files to have a simple Javadoc class comment with at least a @date tag identifying birth, and preferably at least a paragraph on the intended purpose of the class.
* Add the ASF license header comment to all new .java files (copy from existing files in the project)
* Make sure no @author tag added to the file you contribute since @author tag is not used at Apache, other ways such as cvs will record all your contributions fairly.
* Make sure no @author tag gets appended to the file you contribute to as the @author tag is incompatible with Apache. Rest assured, other ways, including CVS, will ensure transparency, fairness in recording your contributions.
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests should be added for a new feature or an important bugfix.
* Sufficient unit-tests should accompany new feature development or non-trivial bug fixes.
* If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project).
* If no-one else is using your branch, please rebase it against the current master (or another target branch in the main project).
* When writing a commit message please follow these conventions, if you are fixing an existing issue please add Fixes #XXX at the end of the commit message (where XXX is the issue number).
* When writing a commit message, please follow the following conventions: should your commit address an open issue, please add Fixes #XXX at the end of the commit message (where XXX is the issue number).
### Contribution flow
This is a rough outline of what a contributor's workflow looks like:
A rough outline of an ideal contributors' workflow is as follows:
* Fork the current repository
* Create a topic branch from where to base the contribution. This is usually master.
* Create a topic branch from where to base the contribution. Mostly, it's the master branch.
* Make commits of logical units.
* Make sure commit messages are in the proper format (see below).
* Make sure the commit messages are in the proper format (see below).
* Push changes in a topic branch to your forked repository.
* Follow the checklist in the [pull request template](https://github.com/apache/dubbo/blob/master/PULL_REQUEST_TEMPLATE.md)
* Before you sending out the pull request, please sync your forked repository with remote repository, this will make your pull request simple and clear. See guide below:
* Before sending out the pull request, please sync your forked repository with the remote repository to ensure that your PR is elegant, concise. Reference the guide below:
```
git remote add upstream git@github.com:apache/dubbo.git
git fetch upstream
@ -62,15 +62,15 @@ Thanks for contributing!
### Code style
We provide a template file [dubbo_codestyle_for_idea.xml](https://github.com/apache/dubbo/tree/master/codestyle/dubbo_codestyle_for_idea.xml) for IntelliJ idea, you can import it to you IDE.
If you use Eclipse you can config manually by referencing the same file.
We provide a template file [dubbo_codestyle_for_idea.xml](https://github.com/apache/dubbo/tree/master/codestyle/dubbo_codestyle_for_idea.xml) for IntelliJ idea that you can import it to your workplace.
If you use Eclipse, you can use the IntelliJ Idea template for manually configuring your file.
**NOTICE**
It is very important to set the dubbo_codestyle_for_idea.xml, otherwise you will fail to pass the Travis CI. Steps to set the code style are as below:
It's critical to set the dubbo_codestyle_for_idea.xml to avoid the failure of your Travis CI builds. Steps to configure the code styles are as follows:
1. Enter `Editor > Code Style`
2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click ![manage profiles](codestyle/manage_profiles.png).
From the drop-down list, select `Import Scheme`, then select this option `IntelliJ IDEA code style XML` to import scheme
2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click on ![manage profiles](codestyle/manage_profiles.png).
From the drop-down list, select `Import Scheme`, then choose the option `IntelliJ IDEA code style XML` to import the scheme.
3. In the Scheme field, type the name of the new scheme and press ⏎ to save the changes.

2
NOTICE
View File

@ -1,5 +1,5 @@
Apache Dubbo
Copyright 2018-2020 The Apache Software Foundation
Copyright 2018-2021 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@ -1,18 +1,16 @@
## What is the purpose of the change
XXXXX
## Brief changelog
XXXXX
## Verifying this change
XXXXX
Follow this checklist to help us incorporate your contribution quickly and easily:
<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->
- [x] Make sure there is a [GITHUB_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
- [x] Make sure there is a [GitHub_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GitHub issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
- [ ] Format the pull request title like `[Dubbo-XXX] Fix UnknownException when host config not exist #XXX`. Each commit in the pull request should have a meaningful subject line and body.
- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.

View File

@ -1,22 +1,22 @@
# Apache Dubbo Project
[![Build Status](https://travis-ci.org/apache/dubbo.svg?branch=master)](https://travis-ci.org/apache/dubbo)
[![codecov](https://codecov.io/gh/apache/dubbo/branch/master/graph/badge.svg)](https://codecov.io/gh/apache/dubbo)
![maven](https://img.shields.io/maven-central/v/org.apache.dubbo/dubbo.svg)
![license](https://img.shields.io/github/license/alibaba/dubbo.svg)
[![Build Status](https://travis-ci.com/apache/dubbo.svg?branch=master)](https://travis-ci.com/apache/dubbo)
[![Codecov](https://codecov.io/gh/apache/dubbo/branch/master/graph/badge.svg)](https://codecov.io/gh/apache/dubbo)
![Maven](https://img.shields.io/maven-central/v/org.apache.dubbo/dubbo.svg)
![License](https://img.shields.io/github/license/alibaba/dubbo.svg)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/dubbo.svg)](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/dubbo.svg)](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Apache%20Dubbo%20is%20a%20high-performance%2C%20java%20based%2C%20open%20source%20RPC%20framework.&url=http://dubbo.apache.org/&via=ApacheDubbo&hashtags=rpc,java,dubbo,micro-service)
[![](https://img.shields.io/twitter/follow/ApacheDubbo.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
[![Twitter Follow](https://img.shields.io/twitter/follow/ApacheDubbo.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
[![Gitter](https://badges.gitter.im/alibaba/dubbo.svg)](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Apache Dubbo is a high-performance, Java based open source RPC framework. Please visit [official site](http://dubbo.apache.org) for quick start and documentations, as well as [Wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit the [official site](http://dubbo.apache.org) for the quick start guide and documentation, as well as the [wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
We are now collecting dubbo user info in order to help us to improve Dubbo better, pls. kindly help us by providing yours on [issue#1012: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/1012), thanks :)
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [issue#1012: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/1012), thanks :)
## Architecture
![Architecture](http://dubbo.apache.org/img/architecture.png)
![Architecture](https://dubbo.apache.org/imgs/architecture.png)
## Features
@ -29,14 +29,14 @@ We are now collecting dubbo user info in order to help us to improve Dubbo bette
## Getting started
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-api). You may clone the sample project and step into `dubbo-samples-api` sub directory before read on.
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
```bash
# git clone https://github.com/apache/dubbo-samples.git
# cd dubbo-samples/java/dubbo-samples-api
# cd dubbo-samples/dubbo-samples-api
```
There's a [README](https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. Read it and try this sample out by following the instructions.
There's a [README](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. We recommend referencing the samples in that directory by following the below-mentioned instructions:
### Maven dependency
@ -44,7 +44,7 @@ There's a [README](https://github.com/apache/dubbo-samples/tree/master/java/dubb
<properties>
<dubbo.version>2.7.8</dubbo.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
@ -70,7 +70,7 @@ public interface GreetingsService {
}
```
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
### Implement service interface for the provider
@ -87,7 +87,7 @@ public class GreetingsServiceImpl implements GreetingsService {
}
```
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
### Start service provider
@ -119,7 +119,7 @@ public class Application {
}
```
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
### Build and run the provider
@ -128,7 +128,7 @@ public class Application {
# mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.provider.Application exec:java
```
### Call remote service in consumer
### Call remote service in the consumer
```java
package org.apache.dubbo.samples.client;
@ -153,7 +153,7 @@ public class Application {
}
}
```
*See [consumer/Application.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
*See [consumer/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
### Build and run the consumer
@ -167,14 +167,14 @@ The consumer will print out `hi, dubbo` on the screen.
### Next steps
* [Your first Dubbo application](http://dubbo.apache.org/en-us/blog/dubbo-101.html) - A 101 tutorial to reveal more details, with the same code above.
* [Dubbo user manual](http://dubbo.apache.org/en-us/docs/user/preface/background.html) - How to use Dubbo and all its features.
* [Dubbo developer guide](http://dubbo.apache.org/en-us/docs/dev/build.html) - How to involve in Dubbo development.
* [Dubbo admin manual](http://dubbo.apache.org/en-us/docs/admin/install/provider-demo.html) - How to admin and manage Dubbo services.
* [Your first Dubbo application](http://dubbo.apache.org/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
* [Dubbo user manual](http://dubbo.apache.org/docs/v2.7/user/preface/background/) - How to use Dubbo and all its features.
* [Dubbo developer guide](http://dubbo.apache.org/docs/v2.7/dev/build/) - How to involve in Dubbo development.
* [Dubbo admin manual](http://dubbo.apache.org/docs/v2.7/admin/install/provider-demo/) - How to admin and manage Dubbo services.
## Building
If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is required to build the master branch)
If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is needed to build the master branch)
```
mvn clean install
@ -182,11 +182,11 @@ If you want to try out the cutting-edge features, you can build with the followi
## Contact
* Mailing list:
* Mailing list:
* dev list: for dev/user discussion. [subscribe](mailto:dev-subscribe@dubbo.apache.org), [unsubscribe](mailto:dev-unsubscribe@dubbo.apache.org), [archive](https://lists.apache.org/list.html?dev@dubbo.apache.org), [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide)
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
## Contributing
@ -195,18 +195,18 @@ See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md)
### How can I contribute?
* Take a look at issues with tag called [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
* Join the discussion on mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
* Take a look at issues with tags marked [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
* Join the discussion on the mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
* Answer questions on [issues](https://github.com/apache/dubbo/issues).
* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us pull request.
* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us a pull request.
* Review the existing [pull request](https://github.com/apache/dubbo/pulls).
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
* blog post
* translation on documentation
* use cases about how Dubbo is being used in enterprise system.
* use cases around the integration of Dubbo in enterprise systems.
* Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
* Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
* Any form of contribution that is not mentioned above.
* Other forms of contribution not explicitly enumerated above.
* If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
## Reporting bugs
@ -215,7 +215,7 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?template
## Reporting a security vulnerability
Please report security vulnerability to [us](mailto:security@dubbo.apache.org) privately.
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
## Dubbo ecosystem
@ -228,12 +228,12 @@ Please report security vulnerability to [us](mailto:security@dubbo.apache.org) p
#### Language
* [Go](https://github.com/dubbo/dubbo-go) (recommended)
* [Node.js](https://github.com/apache/dubbo-js)
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
* [PHP](https://github.com/apache/dubbo-php-framework)
* [Go](https://github.com/dubbo/dubbo-go)
* [Erlang](https://github.com/apache/dubbo-erlang)
## License
Apache Dubbo is under the Apache 2.0 license. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
Apache Dubbo software is licenced under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.

View File

@ -2,7 +2,7 @@
## Supported Versions
Below is a table that shows versions that accept security fix.
Below is a table that shows versions that we accept security fixes.
| Version | Supported |
| ------- | ------------------ |
@ -15,11 +15,11 @@ Below is a table that shows versions that accept security fix.
The Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its software projects. Apache Dubbo is highly sensitive and forthcoming to issues pertaining to its features and functionality.
If you have apprehensions regarding Dubbo's security or you discover vulnerability or potential threat, dont hesitate to get in touch with the Apache Dubbo Security Team by dropping a mail at security@dubbo.apache.org. In the mail, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Dubbo community will get back to you after assessing and analysing the findings.
If you have apprehensions regarding Dubbo's security or you discover vulnerability or potential threat, dont hesitate to get in touch with the Apache Dubbo Security Team by dropping a mail at security@dubbo.apache.org. In the email, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Dubbo community will get back to you after assessing and analysing the findings.
PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain.
## VULNERABILITY HANDLING
## Vulnerability Handling
An overview of the vulnerability handling process is:

View File

@ -54,5 +54,11 @@
<artifactId>zookeeper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -22,7 +22,6 @@ import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
/**
* Cluster. (SPI, Singleton, ThreadSafe)
@ -33,7 +32,8 @@ import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
*/
@SPI(Cluster.DEFAULT)
public interface Cluster {
String DEFAULT = FailoverCluster.NAME;
String DEFAULT = "failover";
/**
* Merge the directory invokers to a virtual invoker.
@ -56,4 +56,4 @@ public interface Cluster {
}
return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
}
}
}

View File

@ -106,4 +106,10 @@ public interface Constants {
String PEER_KEY = "peer";
String CONSUMER_URL_KEY = "CONSUMER_URL";
/**
* prefix of arguments router key
*/
String ARGUMENTS = "arguments";
}

View File

@ -16,16 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.extension.ExtensionLoader;
@ -44,6 +34,18 @@ import org.apache.dubbo.rpc.cluster.router.state.RouterCache;
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
/**
* Router chain
*/
@ -85,7 +87,7 @@ public class RouterChain<T> {
private RouterChain(URL url) {
loopPool = executorRepository.nextExecutorExecutor();
List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class)
.getActivateExtension(url, "router");
.getActivateExtension(url, ROUTER_KEY);
List<Router> routers = extensionFactories.stream()
.map(factory -> factory.getRouter(url))

View File

@ -47,6 +47,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
*/
public abstract class AbstractConfigurator implements Configurator {
private static final String TILDE = "~";
private final URL configuratorUrl;
public AbstractConfigurator(URL url) {
@ -76,7 +78,8 @@ public abstract class AbstractConfigurator implements Configurator {
String configuratorSide = configuratorUrl.getSide();
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
url = configureIfMatch(NetUtils.getLocalHost(), url);
} else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) && url.getPort() == configuratorUrl.getPort()) {
} else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) &&
url.getPort() == configuratorUrl.getPort()) {
url = configureIfMatch(url.getHost(), url);
}
}
@ -137,10 +140,13 @@ public abstract class AbstractConfigurator implements Configurator {
for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (key.startsWith("~") || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
conditionKeys.add(key);
boolean startWithTilde = startWithTilde(key);
if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
if (startWithTilde) {
conditionKeys.add(key);
}
if (value != null && !ANY_VALUE.equals(value)
&& !value.equals(url.getParameter(key.startsWith("~") ? key.substring(1) : key))) {
&& !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
return url;
}
}
@ -152,6 +158,13 @@ public abstract class AbstractConfigurator implements Configurator {
return url;
}
private boolean startWithTilde(String key) {
if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) {
return true;
}
return false;
}
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
}

View File

@ -90,12 +90,14 @@ public class ConfigParser {
parseEnabled(item, config, urlBuilder);
urlBuilder.append("&category=").append(DYNAMIC_CONFIGURATORS_CATEGORY);
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
List<String> apps = item.getApplications();
if (CollectionUtils.isNotEmpty(apps)) {
apps.forEach(app -> urls.add(URL.valueOf(urlBuilder.append("&application=").append(app).toString())));
apps.forEach(app -> {
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
urls.add(URL.valueOf(tmpUrlBuilder.append("&application=").append(app).toString()));
});
} else {
urls.add(URL.valueOf(urlBuilder.toString()));
}
@ -118,17 +120,18 @@ public class ConfigParser {
services.add("*");
}
for (String s : services) {
urlBuilder.append(appendService(s));
urlBuilder.append(toParameterString(item));
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
tmpUrlBuilder.append(appendService(s));
tmpUrlBuilder.append(toParameterString(item));
urlBuilder.append("&application=").append(config.getKey());
tmpUrlBuilder.append("&application=").append(config.getKey());
parseEnabled(item, config, urlBuilder);
parseEnabled(item, config, tmpUrlBuilder);
urlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
urls.add(URL.valueOf(urlBuilder.toString()));
urls.add(URL.valueOf(tmpUrlBuilder.toString()));
}
}
return urls;

View File

@ -35,7 +35,7 @@ public interface GovernanceRuleRepository {
}
/*
/**
* {@link #removeListener(String, String, ConfigurationListener)}
*
* @param key the key to represent a configuration

View File

@ -17,13 +17,11 @@
package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.io.Bytes;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -88,7 +86,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
for (Invoker<T> invoker : invokers) {
String address = invoker.getUrl().getAddress();
for (int i = 0; i < replicaNumber / 4; i++) {
byte[] digest = md5(address + i);
byte[] digest = Bytes.getMD5(address + i);
for (int h = 0; h < 4; h++) {
long m = hash(digest, h);
virtualInvokers.put(m, invoker);
@ -99,7 +97,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
public Invoker<T> select(Invocation invocation) {
String key = toKey(invocation.getArguments());
byte[] digest = md5(key);
byte[] digest = Bytes.getMD5(key);
return selectForKey(hash(digest, 0));
}
@ -128,20 +126,6 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
| (digest[number * 4] & 0xFF))
& 0xFFFFFFFFL;
}
private byte[] md5(String value) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e.getMessage(), e);
}
md5.reset();
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
md5.update(bytes);
return md5.digest();
}
}
}

View File

@ -49,20 +49,17 @@ public class RandomLoadBalance extends AbstractLoadBalance {
int length = invokers.size();
// Every invoker has the same weight?
boolean sameWeight = true;
// the weight of every invokers
// the maxWeight of every invokers, the minWeight = 0 or the maxWeight of the last invoker
int[] weights = new int[length];
// the first invoker's weight
int firstWeight = getWeight(invokers.get(0), invocation);
weights[0] = firstWeight;
// The sum of weights
int totalWeight = firstWeight;
for (int i = 1; i < length; i++) {
int totalWeight = 0;
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
// save for later use
weights[i] = weight;
// Sum
totalWeight += weight;
if (sameWeight && weight != firstWeight) {
// save for later use
weights[i] = totalWeight;
if (sameWeight && totalWeight != weight * (i + 1)) {
sameWeight = false;
}
}
@ -71,8 +68,7 @@ public class RandomLoadBalance extends AbstractLoadBalance {
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// Return a invoker based on the random value.
for (int i = 0; i < length; i++) {
offset -= weights[i];
if (offset < 0) {
if (offset < weights[i]) {
return invokers.get(i);
}
}

View File

@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Constants;
import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
import java.text.ParseException;
@ -50,13 +51,18 @@ import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
/**
* ConditionRouter
*
* It supports the conditional routing configured by "override://", in 2.6.x,
* refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ .
* For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter}
* and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter}
* refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ .
*/
public class ConditionRouter extends AbstractRouter {
public static final String NAME = "condition";
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
protected Map<String, MatchPair> whenCondition;
protected Map<String, MatchPair> thenCondition;
@ -65,7 +71,9 @@ public class ConditionRouter extends AbstractRouter {
public ConditionRouter(String rule, boolean force, boolean enabled) {
this.force = force;
this.enabled = enabled;
this.init(rule);
if (enabled) {
this.init(rule);
}
}
public ConditionRouter(URL url) {
@ -73,7 +81,9 @@ public class ConditionRouter extends AbstractRouter {
this.priority = url.getParameter(PRIORITY_KEY, 0);
this.force = url.getParameter(FORCE_KEY, false);
this.enabled = url.getParameter(ENABLED_KEY, true);
init(url.getParameterAndDecoded(RULE_KEY));
if (enabled) {
init(url.getParameterAndDecoded(RULE_KEY));
}
}
public void init(String rule) {
@ -226,6 +236,16 @@ public class ConditionRouter extends AbstractRouter {
boolean result = false;
for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
String key = matchPair.getKey();
if (key.startsWith(Constants.ARGUMENTS)) {
if (!matchArguments(matchPair, invocation)) {
return false;
} else {
result = true;
continue;
}
}
String sampleValue;
//get real invoked method name from invocation
if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
@ -258,6 +278,45 @@ public class ConditionRouter extends AbstractRouter {
return result;
}
/**
* analysis the arguments in the rule.
* Examples would be like this:
* "arguments[0]=1", whenCondition is that the first argument is equal to '1'.
* "arguments[1]=a", whenCondition is that the second argument is equal to 'a'.
* @param matchPair
* @param invocation
* @return
*/
public boolean matchArguments(Map.Entry<String, MatchPair> matchPair, Invocation invocation) {
try {
// split the rule
String key = matchPair.getKey();
String[] expressArray = key.split("\\.");
String argumentExpress = expressArray[0];
final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress);
if (!matcher.find()) {
return false;
}
//extract the argument index
int index = Integer.parseInt(matcher.group(1));
if (index < 0 || index > invocation.getArguments().length) {
return false;
}
//extract the argument value
Object object = invocation.getArguments()[index];
if (matchPair.getValue().isMatch(String.valueOf(object), null)) {
return true;
}
} catch (Exception e) {
logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e);
}
return false;
}
protected static final class MatchPair {
final Set<String> matches = new HashSet<String>();
final Set<String> mismatches = new HashSet<String>();

View File

@ -22,7 +22,7 @@ import org.apache.dubbo.rpc.cluster.RouterFactory;
/**
* ConditionRouterFactory
*
* Load when "override://" is configured {@link ConditionRouter}
*/
public class ConditionRouterFactory implements RouterFactory {

View File

@ -33,7 +33,6 @@ import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule;
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
import java.net.UnknownHostException;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -160,7 +159,7 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
* @return
*/
private <T> List<Invoker<T>> filterUsingStaticTag(List<Invoker<T>> invokers, URL url, Invocation invocation) {
List<Invoker<T>> result = invokers;
List<Invoker<T>> result;
// Dynamic param
String tag = StringUtils.isEmpty(invocation.getAttachment(TAG_KEY)) ? url.getParameter(TAG_KEY) :
invocation.getAttachment(TAG_KEY);
@ -188,19 +187,11 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
}
private boolean isForceUseTag(Invocation invocation) {
return Boolean.valueOf(invocation.getAttachment(FORCE_USE_TAG, url.getParameter(FORCE_USE_TAG, "false")));
return Boolean.parseBoolean(invocation.getAttachment(FORCE_USE_TAG, url.getParameter(FORCE_USE_TAG, "false")));
}
private <T> List<Invoker<T>> filterInvoker(List<Invoker<T>> invokers, Predicate<Invoker<T>> predicate) {
boolean filter = false;
for (int i = 0; i < invokers.size(); ++i) {
Invoker<T> invoker = invokers.get(i);
if (!predicate.test(invoker)) {
filter = true;
break;
}
}
if (!filter) {
if (invokers.stream().allMatch(predicate)) {
return invokers;
}
@ -226,8 +217,6 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
if ((ANYHOST_VALUE + ":" + port).equals(address)) {
return true;
}
} catch (UnknownHostException e) {
logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
} catch (Exception e) {
logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.Invocation;
@ -30,11 +31,13 @@ import java.util.List;
/**
* BroadcastClusterInvoker
*
*/
public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent";
private static final int MAX_BROADCAST_FAIL_PERCENT = 100;
private static final int MIN_BROADCAST_FAIL_PERCENT = 0;
public BroadcastClusterInvoker(Directory<T> directory) {
super(directory);
@ -47,21 +50,67 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
RpcContext.getServiceContext().setInvokers((List) invokers);
RpcException exception = null;
Result result = null;
URL url = getUrl();
// The value range of broadcast.fail.threshold must be 0100.
// 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown.
// see https://github.com/apache/dubbo/pull/7174
int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT);
if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) {
logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " +
"The current setting is %s, which is reset to 100.", broadcastFailPercent));
broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT;
}
int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT;
int failIndex = 0;
for (Invoker<T> invoker : invokers) {
try {
result = invokeWithContext(invoker, invocation);
} catch (RpcException e) {
exception = e;
logger.warn(e.getMessage(), e);
if (null != result && result.hasException()) {
Throwable resultException = result.getException();
if (null != resultException) {
exception = getRpcException(result.getException());
logger.warn(exception.getMessage(), exception);
if (failIndex == failThresholdIndex) {
break;
} else {
failIndex++;
}
}
}
} catch (Throwable e) {
exception = new RpcException(e.getMessage(), e);
logger.warn(e.getMessage(), e);
exception = getRpcException(e);
logger.warn(exception.getMessage(), exception);
if (failIndex == failThresholdIndex) {
break;
} else {
failIndex++;
}
}
}
if (exception != null) {
if (failIndex == failThresholdIndex) {
logger.debug(
String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex));
} else {
logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
failIndex));
}
throw exception;
}
return result;
}
private RpcException getRpcException(Throwable throwable) {
RpcException rpcException = null;
if (throwable instanceof RpcException) {
rpcException = (RpcException) throwable;
} else {
rpcException = new RpcException(throwable.getMessage(), throwable);
}
return rpcException;
}
}

View File

@ -29,6 +29,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
@ -90,6 +91,9 @@ public class ClusterUtils {
if(map.containsKey(VERSION_KEY)){
copyOfLocalMap.remove(VERSION_KEY);
}
if (map.containsKey(GENERIC_KEY)) {
copyOfLocalMap.remove(GENERIC_KEY);
}
copyOfLocalMap.remove(RELEASE_KEY);
copyOfLocalMap.remove(DUBBO_VERSION_KEY);
@ -99,20 +103,22 @@ public class ClusterUtils {
map.putAll(copyOfLocalMap);
map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY));
if (remoteMap != null) {
map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY));
// Combine filters and listeners on Provider and Consumer
String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
if (remoteFilter != null && remoteFilter.length() > 0
&& localFilter != null && localFilter.length() > 0) {
map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
}
String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
if (remoteListener != null && remoteListener.length() > 0
&& localListener != null && localListener.length() > 0) {
map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
// Combine filters and listeners on Provider and Consumer
String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
if (remoteFilter != null && remoteFilter.length() > 0
&& localFilter != null && localFilter.length() > 0) {
map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
}
String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
if (remoteListener != null && remoteListener.length() > 0
&& localListener != null && localListener.length() > 0) {
map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
}
}
}

View File

@ -58,10 +58,7 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
List<Invoker<T>> copyInvokers = invokers;
checkInvokers(copyInvokers, invocation);
String methodName = RpcUtils.getMethodName(invocation);
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
int len = calculateInvokeTimes(methodName);
// retry loop.
RpcException le = null; // last exception.
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
@ -113,4 +110,19 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
+ le.getMessage(), le.getCause() != null ? le.getCause() : le);
}
private int calculateInvokeTimes(String methodName) {
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
RpcContext rpcContext = RpcContext.getClientAttachment();
Object retry = rpcContext.getObjectAttachment(RETRIES_KEY);
if (retry instanceof Number) {
len = ((Number) retry).intValue() + 1;
rpcContext.removeAttachment(RETRIES_KEY);
}
if (len <= 0) {
len = 1;
}
return len;
}
}

View File

@ -113,7 +113,7 @@ public class MergeableClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (resultList.isEmpty()) {
return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else if (resultList.size() == 1) {
return resultList.iterator().next();
return AsyncRpcResult.newDefaultAsyncResult(resultList.get(0).getValue(), invocation);
}
if (returnType == void.class) {

View File

@ -33,7 +33,6 @@ import java.util.List;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.PREFERRED_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_FORCE;
import static org.apache.dubbo.common.constants.RegistryConstants.ZONE_KEY;
@ -62,7 +61,7 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
.getParameter(REGISTRY_KEY + "." + PREFERRED_KEY, false)) {
.getParameter(PREFERRED_KEY, false)) {
return clusterInvoker.invoke(invocation);
}
}
@ -72,7 +71,7 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (StringUtils.isNotEmpty(zone)) {
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(REGISTRY_KEY + "." + ZONE_KEY))) {
if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(ZONE_KEY))) {
return clusterInvoker.invoke(invocation);
}
}

View File

@ -256,7 +256,7 @@ public abstract class AbstractCluster implements Cluster {
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
// The only purpose is to build a interceptor chain, so the cluster related logic doesn't matter.
// The only purpose is to build an interceptor chain, so the cluster related logic doesn't matter.
return null;
}
}

View File

@ -162,7 +162,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
/**
* Return MockInvoker
* Contract
* directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is present in invocation, otherwise, a list of mock invokers will return.
* directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
* if directory.list() returns more than one mock invoker, only one of them will be used.
*
* @param invocation
@ -174,7 +174,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
if (invocation instanceof RpcInvocation) {
//Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved)
((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString());
//directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is present in invocation, otherwise, a list of mock invokers will return.
//directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
try {
invokers = directory.list(invocation);
} catch (RpcException e) {

View File

@ -131,13 +131,7 @@ public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
recycleTimeField.setAccessible(true);
recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
} catch (NoSuchFieldException e) {
Assertions.assertTrue(true, "getField failed");
} catch (SecurityException e) {
Assertions.assertTrue(true, "getField failed");
} catch (IllegalArgumentException e) {
Assertions.assertTrue(true, "getField failed");
} catch (IllegalAccessException e) {
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException | SecurityException e) {
Assertions.assertTrue(true, "getField failed");
}
}

View File

@ -311,4 +311,38 @@ public class ConditionRouterTest {
Assertions.assertEquals(0, filteredInvokers.size());
}
@Test
public void testRoute_Arguments() {
Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
List<Invoker<String>> invokers = new ArrayList<>();
Invoker<String> invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
Invoker<String> invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
Invoker<String> invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
invokers.add(invoker1);
invokers.add(invoker2);
invokers.add(invoker3);
RpcInvocation invocation = new RpcInvocation();
String p = "a";
invocation.setArguments(new Object[]{null});
List<Invoker<String>> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
Assertions.assertEquals(3, fileredInvokers.size());
invocation.setArguments(new Object[]{p});
fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
Assertions.assertEquals(0, fileredInvokers.size());
router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
Assertions.assertEquals(3, fileredInvokers.size());
router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
Assertions.assertEquals(3, fileredInvokers.size());
int integer = 1;
invocation.setArguments(new Object[]{integer});
router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
Assertions.assertEquals(0, fileredInvokers.size());
}
}

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.Directory;
@ -142,6 +143,33 @@ public class FailoverClusterInvokerTest {
}
}
@Test()
public void testInvoke_retryTimes2() {
int finalRetries = 1;
given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION));
given(invoker1.isAvailable()).willReturn(false);
given(invoker1.getUrl()).willReturn(url);
given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
given(invoker2.invoke(invocation)).willThrow(new RpcException());
given(invoker2.isAvailable()).willReturn(false);
given(invoker2.getUrl()).willReturn(url);
given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
RpcContext rpcContext = RpcContext.getContext();
rpcContext.setAttachment("retries", finalRetries);
FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
try {
Result ret = invoker.invoke(invocation);
assertSame(result, ret);
fail();
} catch (RpcException expected) {
assertTrue((expected.isTimeout() || expected.getCode() == 0));
assertTrue(expected.getMessage().indexOf((finalRetries+1) + " times") > 0);
}
}
@Test()
public void testNoInvoke() {
dic = mock(Directory.class);

View File

@ -18,11 +18,13 @@ package org.apache.dubbo.common;
import org.apache.dubbo.common.utils.StringUtils;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
/**
* 2019-10-10
*/
public class BaseServiceMetadata {
public static final char COLON_SEPERATOR = ':';
public static final char COLON_SEPARATOR = ':';
protected String serviceKey;
protected String serviceInterfaceName;
@ -48,7 +50,7 @@ public class BaseServiceMetadata {
public static String versionFromServiceKey(String serviceKey) {
int index = serviceKey.indexOf(":");
if (index == -1) {
return null;
return DEFAULT_VERSION;
}
return serviceKey.substring(index + 1);
}
@ -77,7 +79,7 @@ public class BaseServiceMetadata {
public String getDisplayServiceKey() {
StringBuilder serviceNameBuilder = new StringBuilder();
serviceNameBuilder.append(serviceInterfaceName);
serviceNameBuilder.append(COLON_SEPERATOR).append(version);
serviceNameBuilder.append(COLON_SEPARATOR).append(version);
return serviceNameBuilder.toString();
}
@ -88,7 +90,7 @@ public class BaseServiceMetadata {
* @return
*/
public static BaseServiceMetadata revertDisplayServiceKey(String displayKey) {
String[] eles = StringUtils.split(displayKey, COLON_SEPERATOR);
String[] eles = StringUtils.split(displayKey, COLON_SEPARATOR);
if (eles == null || eles.length < 1 || eles.length > 2) {
return new BaseServiceMetadata();
}

View File

@ -244,6 +244,9 @@ public class Parameters {
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return parameters.equals(o);
}

View File

@ -48,7 +48,7 @@ import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPERATOR;
import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
@ -1281,7 +1281,7 @@ class URL implements Serializable {
return getServiceInterface();
}
return getServiceInterface() +
COLON_SEPERATOR + getVersion();
COLON_SEPARATOR + getVersion();
}
/**

View File

@ -221,7 +221,7 @@ public final class URLStrParser {
*/
public static URL parseEncodedStr(String encodedURLStr, boolean modifiable) {
Map<String, String> parameters = null;
int pathEndIdx = encodedURLStr.indexOf("%3F");// '?'
int pathEndIdx = encodedURLStr.toUpperCase().indexOf("%3F");// '?'
if (pathEndIdx >= 0) {
parameters = parseEncodedParams(encodedURLStr, pathEndIdx + 3);
} else {

View File

@ -349,7 +349,7 @@ public final class JavaBeanSerializeUtil {
}
}
return cl.newInstance();
return cl.getDeclaredConstructor().newInstance();
}
public static Object getConstructorArg(Class<?> cl) {

View File

@ -340,9 +340,7 @@ public final class ClassGenerator {
return mCtc.toClass(loader, pd);
} catch (RuntimeException e) {
throw e;
} catch (NotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (CannotCompileException e) {
} catch (NotFoundException | CannotCompileException e) {
throw new RuntimeException(e.getMessage(), e);
}
}

View File

@ -49,8 +49,9 @@ public class CustomizedLoaderClassPath implements ClassPath {
public String toString() {
Object cl = null;
if (clref != null)
if (clref != null) {
cl = clref.get();
}
return cl == null ? "<null>" : cl.toString();
}

View File

@ -174,7 +174,7 @@ public abstract class Mixin {
ccm.setSuperClass(Mixin.class.getName());
ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
Class<?> mixin = ccm.toClass();
return (Mixin) mixin.newInstance();
return (Mixin) mixin.getDeclaredConstructor().newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {

View File

@ -187,9 +187,6 @@ public abstract class Proxy {
if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
continue;
}
if (ics[i].isInterface() && Modifier.isStatic(method.getModifiers())) {
continue;
}
worked.add(desc);
int ix = methods.size();

View File

@ -19,11 +19,15 @@ package org.apache.dubbo.common.bytecode;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import javassist.ClassPool;
import javassist.CtMethod;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -31,6 +35,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
/**
* Wrapper.
@ -113,7 +118,7 @@ public abstract class Wrapper {
return OBJECT_WRAPPER;
}
return WRAPPER_MAP.computeIfAbsent(c, key -> makeWrapper(key));
return WRAPPER_MAP.computeIfAbsent(c, Wrapper::makeWrapper);
}
private static Wrapper makeWrapper(Class<?> c) {
@ -150,10 +155,32 @@ public abstract class Wrapper {
pts.put(fn, ft);
}
Method[] methods = c.getMethods();
final ClassPool classPool = new ClassPool(ClassPool.getDefault());
classPool.appendClassPath(new CustomizedLoaderClassPath(cl));
List<String> allMethod = new ArrayList<>();
try {
final CtMethod[] ctMethods = classPool.get(c.getName()).getMethods();
for (CtMethod method : ctMethods) {
allMethod.add(ReflectUtils.getDesc(method));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
Method[] methods = Arrays.stream(c.getMethods())
.filter(method -> allMethod.contains(ReflectUtils.getDesc(method)))
.collect(Collectors.toList())
.toArray(new Method[] {});
// get all public method.
boolean hasMethod = hasMethods(methods);
if (hasMethod) {
Map<String, Integer> sameNameMethodCount = new HashMap<>((int) (methods.length / 0.75f) + 1);
for (Method m : methods) {
sameNameMethodCount.compute(m.getName(),
(key, oldValue) -> oldValue == null ? 1 : oldValue + 1);
}
c3.append(" try{");
for (Method m : methods) {
//ignore Object's method.
@ -166,14 +193,8 @@ public abstract class Wrapper {
int len = m.getParameterTypes().length;
c3.append(" && ").append(" $3.length == ").append(len);
boolean override = false;
for (Method m2 : methods) {
if (m != m2 && m.getName().equals(m2.getName())) {
override = true;
break;
}
}
if (override) {
boolean overload = sameNameMethodCount.get(m.getName()) > 1;
if (overload) {
if (len > 0) {
for (int l = 0; l < len; l++) {
c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
@ -226,7 +247,7 @@ public abstract class Wrapper {
}
}
c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or getter method in class " + c.getName() + ".\"); }");
// make class
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
@ -263,7 +284,7 @@ public abstract class Wrapper {
for (Method m : ms.values()) {
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
}
return (Wrapper) wc.newInstance();
return (Wrapper) wc.getDeclaredConstructor().newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {

View File

@ -22,6 +22,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
@ -48,10 +49,8 @@ public class ClassUtils {
public static Object newInstance(String name) {
try {
return forName(name).newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (IllegalAccessException e) {
return forName(name).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@ -64,7 +63,7 @@ public class ClassUtils {
for (String pkg : packages) {
try {
return classForName(pkg + "." + className);
} catch (ClassNotFoundException e2) {
} catch (ClassNotFoundException ignore) {
}
}
}
@ -123,7 +122,7 @@ public class ClassUtils {
if (className.indexOf('.') == -1) {
try {
return arrayForName("java.lang." + className);
} catch (ClassNotFoundException e2) {
} catch (ClassNotFoundException ignore) {
// ignore, let the original exception be thrown
}
}
@ -431,7 +430,7 @@ public class ClassUtils {
}
return map;
}
/**
* get simple class name from qualified class name
*/
@ -439,7 +438,6 @@ public class ClassUtils {
if (null == qualifiedName) {
return null;
}
int i = qualifiedName.lastIndexOf('.');
return i < 0 ? qualifiedName : qualifiedName.substring(i + 1);
}

View File

@ -16,11 +16,6 @@
*/
package org.apache.dubbo.common.compiler.support;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
@ -30,6 +25,11 @@ import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* CtClassBuilder is builder for CtClass
* <p>
@ -43,17 +43,17 @@ public class CtClassBuilder {
private String superClassName = "java.lang.Object";
private List<String> imports = new ArrayList<>();
private final List<String> imports = new ArrayList<>();
private Map<String, String> fullNames = new HashMap<>();
private final Map<String, String> fullNames = new HashMap<>();
private List<String> ifaces = new ArrayList<>();
private final List<String> ifaces = new ArrayList<>();
private List<String> constructors = new ArrayList<>();
private final List<String> constructors = new ArrayList<>();
private List<String> fields = new ArrayList<>();
private final List<String> fields = new ArrayList<>();
private List<String> methods = new ArrayList<>();
private final List<String> methods = new ArrayList<>();
public String getClassName() {
return className;
@ -146,7 +146,7 @@ public class CtClassBuilder {
CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
// add imported packages
imports.stream().forEach(pool::importPackage);
imports.forEach(pool::importPackage);
// add implemented interfaces
for (String iface : ifaces) {

View File

@ -61,14 +61,22 @@ public class JdkCompiler extends AbstractCompiler {
private final JavaFileManagerImpl javaFileManager;
private volatile List<String> options;
private final List<String> options;
public JdkCompiler() {
options = new ArrayList<String>();
options.add("-source");
options.add("1.6");
options.add("-target");
options.add("1.6");
private static final String DEFAULT_JAVA_VERSION = "1.8";
private static List<String> buildDefaultOptions(String javaVersion) {
return Arrays.asList(
"-source", javaVersion, "-target", javaVersion
);
}
private static List<String> buildDefaultOptions() {
return buildDefaultOptions(DEFAULT_JAVA_VERSION);
}
public JdkCompiler(List<String> options) {
this.options = new ArrayList<>(options);
StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null);
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader instanceof URLClassLoader
@ -93,6 +101,14 @@ public class JdkCompiler extends AbstractCompiler {
javaFileManager = new JavaFileManagerImpl(manager, classLoader);
}
public JdkCompiler() {
this(buildDefaultOptions());
}
public JdkCompiler(String javaVersion) {
this(buildDefaultOptions(javaVersion));
}
@Override
public Class<?> doCompile(String name, String sourceCode) throws Throwable {
int i = name.lastIndexOf('.');
@ -102,7 +118,7 @@ public class JdkCompiler extends AbstractCompiler {
javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
className + ClassUtils.JAVA_EXTENSION, javaFileObject);
Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
null, Arrays.asList(javaFileObject)).call();
null, Collections.singletonList(javaFileObject)).call();
if (result == null || !result) {
throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
}
@ -234,7 +250,7 @@ public class JdkCompiler extends AbstractCompiler {
}
}
private final class ClassLoaderImpl extends ClassLoader {
private static final class ClassLoaderImpl extends ClassLoader {
private final Map<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>();

View File

@ -130,7 +130,7 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
@Override
public boolean removeConfig(String key, String group) {
return execute(() -> doRemoveConfig(key, group), -1L);
return Boolean.TRUE.equals(execute(() -> doRemoveConfig(key, group), -1L));
}
/**

View File

@ -74,8 +74,12 @@ public class ConfigChangedEvent extends EventObject {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ConfigChangedEvent)) return false;
if (this == o) {
return true;
}
if (!(o instanceof ConfigChangedEvent)) {
return false;
}
ConfigChangedEvent that = (ConfigChangedEvent) o;
return Objects.equals(getKey(), that.getKey()) &&
Objects.equals(getGroup(), that.getGroup()) &&

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.config.configcenter;
@Deprecated
public interface Constants {
String CONFIG_CLUSTER_KEY = "config.cluster";
String CONFIG_NAMESPACE_KEY = "config.namespace";

View File

@ -26,7 +26,7 @@ import java.util.TreeSet;
import static java.util.Collections.emptySortedSet;
import static java.util.Collections.unmodifiableSortedSet;
import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
import static org.apache.dubbo.common.utils.PathUtils.buildPath;
@ -87,7 +87,7 @@ public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfig
@Override
public final boolean publishConfig(String key, String group, String content) {
String pathKey = buildPathKey(group, key);
return execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout());
return Boolean.TRUE.equals(execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout()));
}
@Override

View File

@ -0,0 +1,63 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.constants;
/**
* constant for Cluster fault-tolerant mode
*/
public interface ClusterRules {
/**
* When invoke fails, log the initial error and retry other invokers
* (retry n times, which means at most n different invokers will be invoked)
**/
String FAIL_OVER = "failover";
/**
* Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error.
**/
String FAIL_FAST = "failfast";
/**
* When invoke fails, log the error message and ignore this error by returning an empty Result.
**/
String FAIL_SAFE = "failsafe";
/**
* When fails, record failure requests and schedule for retry on a regular interval.
**/
String FAIL_BACK = "failback";
/**
* Invoke a specific number of invokers concurrently, usually used for demanding real-time operations, but need to waste more service resources.
**/
String FORKING = "forking";
/**
* Call all providers by broadcast, call them one by one, and report an error if any one reports an error
**/
String BROADCAST = "broadcast";
String AVAILABLE = "available";
String MERGEABLE = "mergeable";
String EMPTY = "";
}

View File

@ -114,6 +114,8 @@ public interface CommonConstants {
String IO_THREADS_KEY = "iothreads";
String KEEP_ALIVE_KEY = "keep.alive";
int DEFAULT_QUEUES = 0;
int DEFAULT_ALIVE = 60 * 1000;
@ -207,6 +209,8 @@ public interface CommonConstants {
String REMOTE_METADATA_STORAGE_TYPE = "remote";
String GENERIC_KEY = "generic";
/**
* The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
* {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
@ -248,6 +252,11 @@ public interface CommonConstants {
String PORT_KEY = "port";
String DUBBO_IP_TO_BIND = "DUBBO_IP_TO_BIND";
/**
* broadcast cluster.
*/
String BROADCAST_CLUSTER = "broadcast";
/**
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
* the Dubbo application prefers
@ -311,6 +320,8 @@ public interface CommonConstants {
String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
String GENERIC_SERIALIZATION_GSON = "gson";
String GENERIC_SERIALIZATION_DEFAULT = "true";
String GENERIC_SERIALIZATION_BEAN = "bean";
@ -401,4 +412,9 @@ public interface CommonConstants {
String CLUSTER_INTERCEPTOR_COMPATIBLE_KEY = "dubbo.application.cluster.interceptor.compatible";
String UTF8ENCODE = "UTF-8";
/** Pseudo URL prefix for loading from the class path: "classpath:". */
String CLASSPATH_URL_PREFIX = "classpath:";
String DEFAULT_VERSION = "0.0.0";
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.constants;
/**
* constant for Loadbalance strategy
*/
public interface LoadbalanceRules {
/**
* This class select one provider from multiple providers randomly.
**/
String RANDOM = "random";
/**
* Round robin load balance.
**/
String ROUND_ROBIN = "roundrobin";
/**
* Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers.
**/
String LEAST_ACTIVE = "leastactive";
/**
* Consistent Hash, requests with the same parameters are always sent to the same provider.
**/
String CONSISTENT_HASH = "consistenthash";
/**
* Filter the number of invokers with the shortest response time of success calls and count the weights and quantities of these invokers.
**/
String SHORTEST_RESPONSE = "shortestresponse";
String EMPTY = "";
}

View File

@ -114,6 +114,11 @@ public class ExtensionLoader<T> {
private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();
/**
* Record all unacceptable exceptions when using SPI
*/
private Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
public static void setLoadingStrategies(LoadingStrategy... strategies) {
if (ArrayUtils.isNotEmpty(strategies)) {
ExtensionLoader.strategies = strategies;
@ -624,26 +629,25 @@ public class ExtensionLoader<T> {
}
private IllegalStateException findException(String name) {
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
if (entry.getKey().toLowerCase().contains(name.toLowerCase())) {
return entry.getValue();
}
}
StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name);
int i = 1;
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
if (i == 1) {
buf.append(", possible causes: ");
if (entry.getKey().toLowerCase().startsWith(name.toLowerCase())) {
if (i == 1) {
buf.append(", possible causes: ");
}
buf.append("\r\n(");
buf.append(i++);
buf.append(") ");
buf.append(entry.getKey());
buf.append(":\r\n");
buf.append(StringUtils.toString(entry.getValue()));
}
}
buf.append("\r\n(");
buf.append(i++);
buf.append(") ");
buf.append(entry.getKey());
buf.append(":\r\n");
buf.append(StringUtils.toString(entry.getValue()));
if (i == 1) {
buf.append(", no related exception was found, please check whether related SPI module is missing.");
}
return new IllegalStateException(buf.toString());
}
@ -651,13 +655,13 @@ public class ExtensionLoader<T> {
@SuppressWarnings("unchecked")
private T createExtension(String name, boolean wrap) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
if (clazz == null || unacceptableExceptions.contains(name)) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
@ -872,6 +876,7 @@ public class ExtensionLoader<T> {
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
String line;
String clazz = null;
while ((line = reader.readLine()) != null) {
final int ci = line.indexOf('#');
if (ci >= 0) {
@ -884,10 +889,12 @@ public class ExtensionLoader<T> {
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
clazz = line.substring(i + 1).trim();
} else {
clazz = line;
}
if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden);
if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
@ -961,6 +968,8 @@ public class ExtensionLoader<T> {
if (c == null || overridden) {
extensionClasses.put(name, clazz);
} else if (c != clazz) {
// duplicate implementation is unacceptable
unacceptableExceptions.add(name);
String duplicateMsg = "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
logger.error(duplicateMsg);
throw new IllegalStateException(duplicateMsg);

View File

@ -16,9 +16,13 @@
*/
package org.apache.dubbo.common.extension;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* The annotated class will only work as a wrapper when the condition matches.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Wrapper {
/**

View File

@ -259,9 +259,7 @@ class J2oVisitor implements JSONVisitor {
try {
mValue = mType.newInstance();
mWrapper = Wrapper.getWrapper(mType);
} catch (IllegalAccessException e) {
throw new ParseException(StringUtils.toString(e));
} catch (InstantiationException e) {
} catch (IllegalAccessException | InstantiationException e) {
throw new ParseException(StringUtils.toString(e));
}
}
@ -304,9 +302,7 @@ class J2oVisitor implements JSONVisitor {
field.setAccessible(true);
}
field.set(mValue, obj);
} catch (NoSuchFieldException e) {
throw new ParseException(StringUtils.toString(e));
} catch (IllegalAccessException e) {
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new ParseException(StringUtils.toString(e));
}
} else if (!CLASS_PROPERTY.equals(name)) {

View File

@ -63,7 +63,7 @@ public interface Prioritized extends Comparable<Prioritized> {
/**
* Get the priority
*
* @return the default is {@link #MIN_PRIORITY minimum one}
* @return the default is {@link #NORMAL_PRIORITY}
*/
default int getPriority() {
return NORMAL_PRIORITY;

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.threadlocal;
/**
* InternalRunnable
* There is a risk of memory leak when using {@link InternalThreadLocal} without calling
* {@link InternalThreadLocal#removeAll()}.
* This design is learning from {@see io.netty.util.concurrent.FastThreadLocalRunnable} which is in Netty.
*/
public class InternalRunnable implements Runnable{
private final Runnable runnable;
public InternalRunnable(Runnable runnable){
this.runnable=runnable;
}
/**
* After the task execution is completed, it will call {@link InternalThreadLocal#removeAll()} to clear
* unnecessary variables in the thread.
*/
@Override
public void run() {
try{
runnable.run();
}finally {
InternalThreadLocal.removeAll();
}
}
/**
* Wrap ordinary Runnable into {@link InternalThreadLocal}.
*/
static Runnable Wrap(Runnable runnable){
return runnable instanceof InternalRunnable?runnable:new InternalRunnable(runnable);
}
}

View File

@ -58,7 +58,7 @@ public class InternalThreadLocal<V> {
if (v != null && v != InternalThreadLocalMap.UNSET) {
Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
InternalThreadLocal<?>[] variablesToRemoveArray =
variablesToRemove.toArray(new InternalThreadLocal[variablesToRemove.size()]);
variablesToRemove.toArray(new InternalThreadLocal[0]);
for (InternalThreadLocal<?> tlv : variablesToRemoveArray) {
tlv.remove(threadLocalMap);
}

View File

@ -40,7 +40,7 @@ public class NamedInternalThreadFactory extends NamedThreadFactory {
@Override
public Thread newThread(Runnable runnable) {
String name = mPrefix + mThreadNum.getAndIncrement();
InternalThread ret = new InternalThread(mGroup, runnable, name, 0);
InternalThread ret = new InternalThread(mGroup, InternalRunnable.Wrap(runnable), name, 0);
ret.setDaemon(mDaemon);
return ret;
}

View File

@ -32,7 +32,7 @@ import java.util.concurrent.TimeoutException;
/**
* The most important difference between this Executor and other normal Executor is that this one doesn't manage
* any thread.
*
* <p>
* Tasks submitted to this executor through {@link #execute(Runnable)} will not get scheduled to a specific thread, though normal executors always do the schedule.
* Those tasks are stored in a blocking queue and will only be executed when a thread calls {@link #waitAndDrain()}, the thread executing the task
* is exactly the same as the one calling waitAndDrain.
@ -86,7 +86,13 @@ public class ThreadlessExecutor extends AbstractExecutorService {
return;
}
Runnable runnable = queue.take();
Runnable runnable;
try {
runnable = queue.take();
}catch (InterruptedException e){
waiting = false;
throw e;
}
synchronized (lock) {
waiting = false;
@ -95,12 +101,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
runnable = queue.poll();
while (runnable != null) {
try {
runnable.run();
} catch (Throwable t) {
logger.info(t);
}
runnable.run();
runnable = queue.poll();
}
// mark the status of ThreadlessExecutor as finished.
@ -131,6 +132,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
*/
@Override
public void execute(Runnable runnable) {
runnable = new RunnableWrapper(runnable);
synchronized (lock) {
if (!waiting) {
sharedExecutor.execute(runnable);
@ -180,4 +182,21 @@ public class ThreadlessExecutor extends AbstractExecutorService {
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return false;
}
private static class RunnableWrapper implements Runnable {
private Runnable runnable;
public RunnableWrapper(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
try {
runnable.run();
} catch (Throwable t) {
logger.info(t);
}
}
}
}

View File

@ -16,6 +16,14 @@
*/
package org.apache.dubbo.common.threadpool.support;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent;
import org.apache.dubbo.common.utils.JVMUtil;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.event.EventDispatcher;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
@ -26,13 +34,7 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent;
import org.apache.dubbo.common.utils.JVMUtil;
import org.apache.dubbo.event.EventDispatcher;
import static java.lang.String.format;
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
/**
@ -61,6 +63,8 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
private static Semaphore guard = new Semaphore(1);
private static final String USER_HOME = System.getProperty("user.home");
public AbortPolicyWithReport(String threadName, URL url) {
this.threadName = threadName;
this.url = url;
@ -104,7 +108,7 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(() -> {
String dumpPath = url.getParameter(DUMP_DIRECTORY, System.getProperty("user.home"));
String dumpPath = getDumpPath();
SimpleDateFormat sdf;
@ -134,4 +138,21 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
}
private String getDumpPath() {
final String dumpPath = url.getParameter(DUMP_DIRECTORY);
if (StringUtils.isEmpty(dumpPath)) {
return USER_HOME;
}
final File dumpDirectory = new File(dumpPath);
if (!dumpDirectory.exists()) {
if (dumpDirectory.mkdirs()) {
logger.info(format("Dubbo dump directory[%s] created", dumpDirectory.getAbsolutePath()));
} else {
logger.warn(format("Dubbo dump directory[%s] can't be created, use the 'user.home'[%s]",
dumpDirectory.getAbsolutePath(), USER_HOME));
return USER_HOME;
}
}
return dumpPath;
}
}

View File

@ -805,8 +805,10 @@ public class HashedWheelTimer implements Timer {
return head;
}
}
private static final boolean IS_OS_WINDOWS = System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
private boolean isWindows() {
return System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
return IS_OS_WINDOWS;
}
}

View File

@ -37,6 +37,7 @@ import java.util.StringJoiner;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
/**
* A class which store parameters for {@link URL}
@ -178,7 +179,7 @@ public class URLParam implements Serializable {
* Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
*
* @param method method name
* @param key key
* @param key key
* @return value
*/
public String getMethodParameter(String method, String key) {
@ -191,7 +192,7 @@ public class URLParam implements Serializable {
* Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
*
* @param method method name
* @param key key
* @param key key
* @return value
*/
public String getMethodParameterStrict(String method, String key) {
@ -853,10 +854,27 @@ public class URLParam implements Serializable {
return false;
}
URLParam urlParam = (URLParam) o;
return Objects.equals(KEY, urlParam.KEY)
if (Objects.equals(KEY, urlParam.KEY)
&& Objects.equals(DEFAULT_KEY, urlParam.DEFAULT_KEY)
&& Arrays.equals(VALUE, urlParam.VALUE)
&& Objects.equals(EXTRA_PARAMS, urlParam.EXTRA_PARAMS);
&& Arrays.equals(VALUE, urlParam.VALUE)) {
if (CollectionUtils.isNotEmptyMap(EXTRA_PARAMS)) {
if (CollectionUtils.isEmptyMap(urlParam.EXTRA_PARAMS) || EXTRA_PARAMS.size() != urlParam.EXTRA_PARAMS.size()) {
return false;
}
for (Map.Entry<String, String> entry : EXTRA_PARAMS.entrySet()) {
if (TIMESTAMP_KEY.equals(entry.getKey())) {
continue;
}
if (!entry.getValue().equals(urlParam.EXTRA_PARAMS.get(entry.getKey()))) {
return false;
}
}
return true;
}
return CollectionUtils.isEmptyMap(urlParam.EXTRA_PARAMS);
}
return false;
}
private int hashCodeCache = -1;
@ -864,7 +882,11 @@ public class URLParam implements Serializable {
@Override
public int hashCode() {
if (hashCodeCache == -1) {
hashCodeCache = EXTRA_PARAMS.hashCode();
for (Map.Entry<String, String> entry : EXTRA_PARAMS.entrySet()) {
if (!TIMESTAMP_KEY.equals(entry.getKey())) {
hashCodeCache = hashCodeCache * 31 + Objects.hashCode(entry);
}
}
for (Integer value : VALUE) {
hashCodeCache = hashCodeCache * 31 + value;
}

View File

@ -22,6 +22,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
@ -40,6 +41,7 @@ import static org.apache.dubbo.common.function.Streams.filterFirst;
import static org.apache.dubbo.common.utils.ClassUtils.getAllInheritedTypes;
import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
import static org.apache.dubbo.common.utils.CollectionUtils.first;
import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
/**
@ -449,4 +451,32 @@ public interface AnnotationUtils {
Class<? extends Annotation>... annotationTypes) {
return isAnnotationPresent(type, false, annotationTypes);
}
/**
* Get the default value of attribute on the specified annotation
*
* @param annotation {@link Annotation} object
* @param attributeName the name of attribute
* @param <T> the type of value
* @return <code>null</code> if not found
* @since 2.7.9
*/
static <T> T getDefaultValue(Annotation annotation, String attributeName) {
return getDefaultValue(annotation.annotationType(), attributeName);
}
/**
* Get the default value of attribute on the specified annotation
*
* @param annotationType the type of {@link Annotation}
* @param attributeName the name of attribute
* @param <T> the type of value
* @return <code>null</code> if not found
* @since 2.7.9
*/
static <T> T getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
Method method = findMethod(annotationType, attributeName);
return (T) (method == null ? null : method.getDefaultValue());
}
}

View File

@ -66,4 +66,16 @@ public final class ArrayUtils {
return -1;
}
}
/**
* Convert from variable arguments to array
*
* @param values variable arguments
* @param <T> The class
* @return array
* @since 2.7.9
*/
public static <T> T[] of(T... values) {
return values;
}
}

View File

@ -43,21 +43,6 @@ public class ClassUtils {
* Suffix for array class names: "[]"
*/
public static final String ARRAY_SUFFIX = "[]";
/**
* Prefix for internal array class names: "[L"
*/
private static final String INTERNAL_ARRAY_PREFIX = "[L";
/**
* Map with primitive type name as key and corresponding primitive type as
* value, for example: "int" -> "int.class".
*/
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new HashMap<String, Class<?>>(32);
/**
* Map with primitive wrapper type as key and corresponding primitive type
* as value, for example: Integer.class -> int.class.
*/
private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
/**
* Simple Types including:
* <ul>
@ -94,7 +79,20 @@ public class ClassUtils {
Date.class,
Object.class
);
/**
* Prefix for internal array class names: "[L"
*/
private static final String INTERNAL_ARRAY_PREFIX = "[L";
/**
* Map with primitive type name as key and corresponding primitive type as
* value, for example: "int" -> "int.class".
*/
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new HashMap<String, Class<?>>(32);
/**
* Map with primitive wrapper type as key and corresponding primitive type
* as value, for example: Integer.class -> int.class.
*/
private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
private static final char PACKAGE_SEPARATOR_CHAR = '.';
static {

View File

@ -39,28 +39,25 @@ import static java.util.Collections.unmodifiableSet;
*/
public class CollectionUtils {
private static final Comparator<String> SIMPLE_NAME_COMPARATOR = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
if (s1 == null && s2 == null) {
return 0;
}
if (s1 == null) {
return -1;
}
if (s2 == null) {
return 1;
}
int i1 = s1.lastIndexOf('.');
if (i1 >= 0) {
s1 = s1.substring(i1 + 1);
}
int i2 = s2.lastIndexOf('.');
if (i2 >= 0) {
s2 = s2.substring(i2 + 1);
}
return s1.compareToIgnoreCase(s2);
private static final Comparator<String> SIMPLE_NAME_COMPARATOR = (s1, s2) -> {
if (s1 == null && s2 == null) {
return 0;
}
if (s1 == null) {
return -1;
}
if (s2 == null) {
return 1;
}
int i1 = s1.lastIndexOf('.');
if (i1 >= 0) {
s1 = s1.substring(i1 + 1);
}
int i2 = s2.lastIndexOf('.');
if (i2 >= 0) {
s2 = s2.substring(i2 + 1);
}
return s1.compareToIgnoreCase(s2);
};
private CollectionUtils() {
@ -324,9 +321,7 @@ public class CollectionUtils {
try {
return one.containsAll(another);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}

View File

@ -21,6 +21,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
@ -111,17 +112,23 @@ public class CompatibleTypeUtils {
+ DATE_FORMAT + ", cause: " + e.getMessage(), e);
}
}
if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class
|| type == java.time.LocalTime.class) {
LocalDateTime localDateTime = LocalDateTime.parse(string);
if (type == java.time.LocalDate.class) {
return localDateTime.toLocalDate();
if (type == java.time.LocalDateTime.class) {
if (StringUtils.isEmpty(string)) {
return null;
}
if (type == java.time.LocalTime.class) {
return localDateTime.toLocalTime();
return LocalDateTime.parse(string);
}
if (type == java.time.LocalDate.class) {
if (StringUtils.isEmpty(string)) {
return null;
}
return localDateTime;
return LocalDate.parse(string);
}
if (type == java.time.LocalTime.class) {
if (StringUtils.isEmpty(string)) {
return null;
}
return LocalDateTime.parse(string).toLocalTime();
}
if (type == Class.class) {
try {
@ -200,19 +207,19 @@ public class CompatibleTypeUtils {
}
}
if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {
int length = Array.getLength(value);
Collection collection;
if (!type.isInterface()) {
try {
collection = (Collection) type.newInstance();
} catch (Throwable e) {
collection = new ArrayList<Object>();
collection = new ArrayList<Object>(length);
}
} else if (type == Set.class) {
collection = new HashSet<Object>();
collection = new HashSet<Object>(Math.max((int) (length/.75f) + 1, 16));
} else {
collection = new ArrayList<Object>();
collection = new ArrayList<Object>(length);
}
int length = Array.getLength(value);
for (int i = 0; i < length; i++) {
collection.add(Array.get(value, i));
}

View File

@ -60,9 +60,7 @@ public class ExecutorUtil {
try {
// Disable new tasks from being submitted
es.shutdown();
} catch (SecurityException ex2) {
return;
} catch (NullPointerException ex2) {
} catch (SecurityException | NullPointerException ex2) {
return;
}
try {
@ -86,9 +84,7 @@ public class ExecutorUtil {
final ExecutorService es = (ExecutorService) executor;
try {
es.shutdownNow();
} catch (SecurityException ex2) {
return;
} catch (NullPointerException ex2) {
} catch (SecurityException | NullPointerException ex2) {
return;
}
try {

View File

@ -62,6 +62,11 @@ public interface FieldUtils {
break;
}
}
if (field == null) {
throw new IllegalStateException(String.format("cannot find field %s,field is null", fieldName));
}
return field;
}

View File

@ -16,9 +16,12 @@
*/
package org.apache.dubbo.common.utils;
import org.apache.dubbo.common.constants.CommonConstants;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -30,6 +33,8 @@ import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@ -228,4 +233,38 @@ public class IOUtils {
writeLines(new FileOutputStream(file, true), lines);
}
/**
* use like spring code
* @param resourceLocation
* @return
*/
public static URL getURL(String resourceLocation) throws FileNotFoundException {
Assert.notNull(resourceLocation, "Resource location must not be null");
if (resourceLocation.startsWith(CommonConstants.CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CommonConstants.CLASSPATH_URL_PREFIX.length());
ClassLoader cl = ClassUtils.getClassLoader();
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
if (url == null) {
String description = "class path resource [" + path + "]";
throw new FileNotFoundException(description +
" cannot be resolved to URL because it does not exist");
}
return url;
}
try {
// try URL
return new URL(resourceLocation);
}
catch (MalformedURLException ex) {
// no URL -> treat as file path
try {
return new File(resourceLocation).toURI().toURL();
}
catch (MalformedURLException ex2) {
throw new FileNotFoundException("Resource location [" + resourceLocation +
"] is neither a URL not a well-formed file path");
}
}
}
}

View File

@ -30,12 +30,12 @@ public class LFUCache<K, V> {
private int curSize = 0;
private final ReentrantLock lock = new ReentrantLock();
private static final int DEFAULT_LOAD_FACTOR = 1000;
private static final int DEFAULT_INITIAL_CAPACITY = 1000;
private static final float DEFAULT_EVICTION_CAPACITY = 0.75f;
private static final float DEFAULT_EVICTION_FACTOR = 0.75f;
public LFUCache() {
this(DEFAULT_LOAD_FACTOR, DEFAULT_EVICTION_CAPACITY);
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_EVICTION_FACTOR);
}
/**
@ -46,12 +46,13 @@ public class LFUCache<K, V> {
* @param maxCapacity cache max capacity
* @param evictionFactor cache proceedEviction factor
*/
@SuppressWarnings("unchecked")
public LFUCache(final int maxCapacity, final float evictionFactor) {
if (maxCapacity <= 0) {
throw new IllegalArgumentException("Illegal initial capacity: " +
maxCapacity);
}
boolean factorInRange = evictionFactor <= 1 || evictionFactor < 0;
boolean factorInRange = evictionFactor <= 1 && evictionFactor > 0;
if (!factorInRange || Float.isNaN(evictionFactor)) {
throw new IllegalArgumentException("Illegal eviction factor value:"
+ evictionFactor);
@ -61,7 +62,7 @@ public class LFUCache<K, V> {
this.map = new HashMap<>();
this.freqTable = new CacheDeque[capacity + 1];
for (int i = 0; i <= capacity; i++) {
freqTable[i] = new CacheDeque<K, V>();
freqTable[i] = new CacheDeque<>();
}
for (int i = 0; i < capacity; i++) {
freqTable[i].nextDeque = freqTable[i + 1];
@ -77,11 +78,9 @@ public class LFUCache<K, V> {
CacheNode<K, V> node;
lock.lock();
try {
if (map.containsKey(key)) {
node = map.get(key);
if (node != null) {
CacheNode.withdrawNode(node);
}
node = map.get(key);
if (node != null) {
CacheNode.withdrawNode(node);
node.value = value;
freqTable[0].addLastNode(node);
map.put(key, node);
@ -171,7 +170,7 @@ public class LFUCache<K, V> {
CacheNode<K, V> next;
K key;
V value;
CacheDeque owner;
CacheDeque<K, V> owner;
CacheNode() {
}

View File

@ -34,6 +34,7 @@ import static org.apache.dubbo.common.utils.MemberUtils.isPrivate;
import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
import static org.apache.dubbo.common.utils.ReflectUtils.EMPTY_CLASS_ARRAY;
import static org.apache.dubbo.common.utils.ReflectUtils.resolveTypes;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
/**
* Miscellaneous method utility methods.
@ -50,7 +51,7 @@ public interface MethodUtils {
* @param method the method to check
* @return whether the given method is setter method
*/
public static boolean isSetter(Method method) {
static boolean isSetter(Method method) {
return method.getName().startsWith("set")
&& !"set".equals(method.getName())
&& Modifier.isPublic(method.getModifiers())
@ -65,7 +66,7 @@ public interface MethodUtils {
* @param method the method to check
* @return whether the given method is getter method
*/
public static boolean isGetter(Method method) {
static boolean isGetter(Method method) {
String name = method.getName();
return (name.startsWith("get") || name.startsWith("is"))
&& !"get".equals(name) && !"is".equals(name)
@ -82,7 +83,7 @@ public interface MethodUtils {
* @param method the method to check
* @return whether the given method is meta method
*/
public static boolean isMetaMethod(Method method) {
static boolean isMetaMethod(Method method) {
String name = method.getName();
if (!(name.startsWith("get") || name.startsWith("is"))) {
return false;
@ -113,12 +114,11 @@ public interface MethodUtils {
* @param method the method to check
* @return whether the given method is deprecated method
*/
public static boolean isDeprecated(Method method) {
static boolean isDeprecated(Method method) {
return method.getAnnotation(Deprecated.class) != null;
}
/**
* Create an instance of {@link Predicate} for {@link Method} to exclude the specified declared class
*
@ -252,7 +252,9 @@ public interface MethodUtils {
static Method findMethod(Class type, String methodName, Class<?>... parameterTypes) {
Method method = null;
try {
method = type.getDeclaredMethod(methodName, parameterTypes);
if (type != null && isNotEmpty(methodName)) {
method = type.getDeclaredMethod(methodName, parameterTypes);
}
} catch (NoSuchMethodException e) {
}
return method;
@ -274,6 +276,10 @@ public interface MethodUtils {
Method method = findMethod(type, methodName, parameterTypes);
T value = null;
if (method == null) {
throw new IllegalStateException(String.format("cannot find method %s,class: %s", methodName, type.getName()));
}
try {
final boolean isAccessible = method.isAccessible();

View File

@ -235,7 +235,9 @@ public class NetUtils {
return configIp;
}
return getIpByHost(getLocalAddress().getHostName());
InetAddress localAddress = getLocalAddress();
String hostName = localAddress == null ? LOCALHOST_VALUE : localAddress.getHostName();
return getIpByHost(hostName);
}
/**
@ -471,10 +473,8 @@ public class NetUtils {
public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
boolean interfaceSet = false;
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface i = (NetworkInterface) interfaces.nextElement();
Enumeration addresses = i.getInetAddresses();
for (NetworkInterface networkInterface : getValidNetworkInterfaces()) {
Enumeration addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = (InetAddress) addresses.nextElement();
if (preferIpv6 && address instanceof Inet6Address) {

View File

@ -173,6 +173,7 @@ public class PojoUtils {
}
for (Method method : pojo.getClass().getMethods()) {
if (ReflectUtils.isBeanPropertyReadMethod(method)) {
ReflectUtils.makeAccessible(method);
try {
map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));
} catch (Exception e) {
@ -588,11 +589,7 @@ public class PojoUtils {
constructor.setAccessible(true);
Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray();
return constructor.newInstance(parameters);
} catch (InstantiationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (InvocationTargetException e) {
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@ -608,9 +605,15 @@ public class PojoUtils {
if ("char".equals(parameterType.getName())) {
return Character.MIN_VALUE;
}
if ("bool".equals(parameterType.getName())) {
if ("boolean".equals(parameterType.getName())) {
return false;
}
if ("byte".equals(parameterType.getName())) {
return (byte) 0;
}
if ("short".equals(parameterType.getName())) {
return (short) 0;
}
return parameterType.isPrimitive() ? 0 : null;
}

View File

@ -31,6 +31,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
@ -154,8 +155,8 @@ public final class ReflectUtils {
}
public static boolean isPrimitives(Class<?> cls) {
if (cls.isArray()) {
return isPrimitive(cls.getComponentType());
while (cls.isArray()) {
cls = cls.getComponentType();
}
return isPrimitive(cls);
}
@ -904,7 +905,9 @@ public final class ReflectUtils {
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws IllegalStateException when multiple methods are found (overridden method when parameter info is not provided)
* @deprecated Recommend {@link MethodUtils#findMethod(Class, String, Class[])}
*/
@Deprecated
public static Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes)
throws NoSuchMethodException, ClassNotFoundException {
String signature = clazz.getName() + "." + methodName;
@ -943,6 +946,16 @@ public final class ReflectUtils {
return method;
}
/**
* @param clazz Target class to find method
* @param methodName Method signature, e.g.: method1(int, String). It is allowed to provide method name only, e.g.: method2
* @return target method
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws IllegalStateException when multiple methods are found (overridden method when parameter info is not provided)
* @deprecated Recommend {@link MethodUtils#findMethod(Class, String, Class[])}
*/
@Deprecated
public static Method findMethodByMethodName(Class<?> clazz, String methodName)
throws NoSuchMethodException, ClassNotFoundException {
return findMethodByMethodSignature(clazz, methodName, null);
@ -1051,7 +1064,7 @@ public final class ReflectUtils {
try {
Object value = emptyInstances.get(returnType);
if (value == null) {
value = returnType.newInstance();
value = returnType.getDeclaredConstructor().newInstance();
emptyInstances.put(returnType, value);
}
Class<?> cls = value.getClass();
@ -1190,6 +1203,9 @@ public final class ReflectUtils {
if (actualArgType instanceof ParameterizedType) {
returnType = (Class<?>) ((ParameterizedType) actualArgType).getRawType();
genericReturnType = actualArgType;
} else if (actualArgType instanceof TypeVariable) {
returnType = (Class<?>) ((TypeVariable<?>) actualArgType).getBounds()[0];
genericReturnType = actualArgType;
} else {
returnType = (Class<?>) actualArgType;
genericReturnType = returnType;
@ -1217,16 +1233,14 @@ public final class ReflectUtils {
Set<ParameterizedType> parameterizedTypes = genericTypes.stream()
.filter(type -> type instanceof ParameterizedType)// filter ParameterizedType
.map(type -> ParameterizedType.class.cast(type)) // cast to ParameterizedType
.map(ParameterizedType.class::cast) // cast to ParameterizedType
.collect(Collectors.toSet());
if (parameterizedTypes.isEmpty()) { // If not found, try to search super types recursively
genericTypes.stream()
.filter(type -> type instanceof Class)
.map(type -> Class.class.cast(type))
.forEach(superClass -> {
parameterizedTypes.addAll(findParameterizedTypes(superClass));
});
.map(Class.class::cast)
.forEach(superClass -> parameterizedTypes.addAll(findParameterizedTypes(superClass)));
}
return unmodifiableSet(parameterizedTypes); // build as a Set
@ -1316,4 +1330,21 @@ public final class ReflectUtils {
return types;
}
}
/**
* Copy from org.springframework.util.ReflectionUtils.
* Make the given method accessible, explicitly setting it accessible if
* necessary. The {@code setAccessible(true)} method is only called
* when actually necessary, to avoid unnecessary conflicts with a JVM
* SecurityManager (if active).
* @param method the method to make accessible
* @see java.lang.reflect.Method#setAccessible
*/
@SuppressWarnings("deprecation") // on JDK 9
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) ||
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
method.setAccessible(true);
}
}
}

View File

@ -16,11 +16,15 @@
*/
package org.apache.dubbo.common.utils;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Service;
import java.lang.annotation.Annotation;
import java.util.List;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
import static org.apache.dubbo.common.utils.ClassUtils.isGenericClass;
@ -36,6 +40,13 @@ import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
*/
public class ServiceAnnotationResolver {
/**
* The annotation {@link Class classes} of Dubbo Service (read-only)
*
* @since 2.7.9
*/
public static List<Class<? extends Annotation>> SERVICE_ANNOTATION_CLASSES = unmodifiableList(asList(DubboService.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
private final Annotation serviceAnnotation;
private final Class<?> serviceType;
@ -47,16 +58,18 @@ public class ServiceAnnotationResolver {
private Annotation getServiceAnnotation(Class<?> serviceType) {
Annotation serviceAnnotation = serviceType.getAnnotation(Service.class);
Annotation serviceAnnotation = null;
if (serviceAnnotation == null) {
serviceAnnotation = serviceType.getAnnotation(com.alibaba.dubbo.config.annotation.Service.class);
for (Class<? extends Annotation> serviceAnnotationClass : SERVICE_ANNOTATION_CLASSES) {
serviceAnnotation = serviceType.getAnnotation(serviceAnnotationClass);
if (serviceAnnotation != null) {
break;
}
}
if (serviceAnnotation == null) {
throw new IllegalArgumentException(format("@%s or @%s can't be found in the service type[%s].",
Service.class.getName(),
com.alibaba.dubbo.config.annotation.Service.class.getName(),
throw new IllegalArgumentException(format("Any annotation of [%s] can't be annotated in the service type[%s].",
SERVICE_ANNOTATION_CLASSES,
serviceType.getName()
));
}

View File

@ -200,11 +200,7 @@ public class UrlUtils {
if (version != null && version.length() > 0) {
name = name + ":" + version;
}
Map<String, String> newUrls = newRegister.get(name);
if (newUrls == null) {
newUrls = new HashMap<String, String>();
newRegister.put(name, newUrls);
}
Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>());
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
}
} else {
@ -261,11 +257,7 @@ public class UrlUtils {
params.put("version", name.substring(i + 1));
name = name.substring(0, i);
}
Map<String, String> newUrls = newRegister.get(name);
if (newUrls == null) {
newUrls = new HashMap<String, String>();
newRegister.put(name, newUrls);
}
Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<String, String>());
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
}
} else {
@ -324,11 +316,7 @@ public class UrlUtils {
if (version != null && version.length() > 0) {
name = name + ":" + version;
}
Map<String, String> newUrls = newNotify.get(name);
if (newUrls == null) {
newUrls = new HashMap<String, String>();
newNotify.put(name, newUrls);
}
Map<String, String> newUrls = newNotify.computeIfAbsent(name, k -> new HashMap<String, String>());
newUrls.put(url, StringUtils.toQueryString(params));
}
}

View File

@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.model.AsyncMethodInfo;
import javax.annotation.PostConstruct;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
@ -86,6 +87,11 @@ public abstract class AbstractConfig implements Serializable {
protected final AtomicBoolean refreshed = new AtomicBoolean(false);
/**
* Is default or not
*/
protected Boolean isDefault;
private static String convertLegacyValue(String key, String value) {
if (value != null && value.length() > 0) {
if ("dubbo.service.max.retry.providers".equals(key)) {
@ -373,6 +379,7 @@ public abstract class AbstractConfig implements Serializable {
Method[] methods = annotationClass.getMethods();
for (Method method : methods) {
if (method.getDeclaringClass() != Object.class
&& method.getDeclaringClass()!= Annotation.class
&& method.getReturnType() != void.class
&& method.getParameterTypes().length == 0
&& Modifier.isPublic(method.getModifiers())
@ -536,7 +543,7 @@ public abstract class AbstractConfig implements Serializable {
buf.append(" ");
buf.append(key);
buf.append("=\"");
buf.append(value);
buf.append(key.equals("password") ? "******" : value);
buf.append("\"");
}
}
@ -628,4 +635,12 @@ public abstract class AbstractConfig implements Serializable {
return hashCode;
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
}

View File

@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import java.util.ArrayList;
import java.util.Arrays;
@ -52,6 +53,21 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
private static final long serialVersionUID = -1559314110797223229L;
/**
* The interface name of the exported service
*/
protected String interfaceName;
/**
* The remote service version the customer/provider side will reference
*/
protected String version;
/**
* The remote service group the customer/provider side will reference
*/
protected String group;
protected ServiceMetadata serviceMetadata;
/**
* Local impl class name for the service interface
*/
@ -312,6 +328,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
protected boolean notHasSelfRegistryProperty() {
return CollectionUtils.isEmpty(registries) && StringUtils.isEmpty(registryIds);
}
public void completeCompoundConfigs(AbstractInterfaceConfig interfaceConfig) {
if (interfaceConfig != null) {
if (application == null) {
@ -320,15 +340,16 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (module == null) {
setModule(interfaceConfig.getModule());
}
if (registries == null) {
if (notHasSelfRegistryProperty()) {
setRegistries(interfaceConfig.getRegistries());
setRegistryIds(interfaceConfig.getRegistryIds());
}
if (monitor == null) {
setMonitor(interfaceConfig.getMonitor());
}
}
if (module != null) {
if (registries == null) {
if (notHasSelfRegistryProperty()) {
setRegistries(module.getRegistries());
}
if (monitor == null) {
@ -336,8 +357,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
}
if (application != null) {
if (registries == null) {
if (notHasSelfRegistryProperty()) {
setRegistries(application.getRegistries());
setRegistryIds(application.getRegistryIds());
}
if (monitor == null) {
setMonitor(application.getMonitor());
@ -346,10 +368,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
protected void computeValidRegistryIds() {
if (StringUtils.isEmpty(getRegistryIds())) {
if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryIds())) {
setRegistryIds(getApplication().getRegistryIds());
}
if (application != null && notHasSelfRegistryProperty()) {
setRegistries(application.getRegistries());
setRegistryIds(application.getRegistryIds());
}
}
@ -691,4 +712,46 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public SslConfig getSslConfig() {
return ApplicationModel.getConfigManager().getSsl().orElse(null);
}
public void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
serviceMetadata.setVersion(getVersion(interfaceConfig));
serviceMetadata.setGroup(getGroup(interfaceConfig));
serviceMetadata.setDefaultGroup(getGroup(interfaceConfig));
serviceMetadata.setServiceInterfaceName(getInterface());
}
public String getGroup(AbstractInterfaceConfig interfaceConfig) {
return StringUtils.isEmpty(this.group) ? (interfaceConfig != null ? interfaceConfig.getGroup() : this.group) : this.group;
}
public String getVersion(AbstractInterfaceConfig interfaceConfig) {
return StringUtils.isEmpty(this.version) ? (interfaceConfig != null ? interfaceConfig.getVersion() : this.version) : this.version;
}
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 String getInterface() {
return interfaceName;
}
public void setInterface(String interfaceName) {
this.interfaceName = interfaceName;
// if (StringUtils.isEmpty(id)) {
// id = interfaceName;
// }
}
}

View File

@ -71,15 +71,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
//TODO solve merge problem
protected Boolean stubevent;//= Constants.DEFAULT_STUB_EVENT;
/**
* The remote service version the customer side will reference
*/
protected String version;
/**
* The remote service group the customer side will reference
*/
protected String group;
/**
* declares which app or service this interface belongs to
@ -212,21 +204,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
this.sticky = sticky;
}
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;
}
@Parameter(key = "provided-by")
public String getProvidedBy() {

View File

@ -112,11 +112,6 @@ public class ApplicationConfig extends AbstractConfig {
*/
private MonitorConfig monitor;
/**
* Is default or not
*/
private Boolean isDefault;
/**
* Directory for saving thread dump
*/
@ -320,14 +315,6 @@ public class ApplicationConfig extends AbstractConfig {
LoggerFactory.setLoggerAdapter(logger);
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
@Parameter(key = DUMP_DIRECTORY)
public String getDumpDirectory() {
return dumpDirectory;

View File

@ -119,4 +119,6 @@ public interface Constants {
String MULTI_SERIALIZATION_KEY = "serialize.multiple";
String[] DOT_COMPATIBLE_KEYS = new String[]{"qos-enable", "qos-port", "qos-accept-foreign-ip"};
String IGNORE_CHECK_KEYS = "ignoreCheckKeys";
}

View File

@ -27,11 +27,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
private static final long serialVersionUID = 2827274711143680600L;
/**
* Whether to use the default protocol
*/
private Boolean isDefault;
/**
* Networking framework client uses: netty, mina, etc.
*/
@ -72,11 +67,7 @@ public class ConsumerConfig extends AbstractReferenceConfig {
System.setProperty("sun.rmi.transport.tcp.responseTimeout", String.valueOf(timeout));
}
}
public Boolean isDefault() {
return isDefault;
}
public String getClient() {
return client;
}
@ -93,14 +84,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
this.threadpool = threadpool;
}
public Boolean getDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
public Integer getCorethreads() {
return corethreads;
}

View File

@ -85,6 +85,12 @@ public class MetadataReportConfig extends AbstractConfig {
*/
private String registry;
/**
* File for saving metadata center dynamic list
*/
private String file;
public MetadataReportConfig() {
}
@ -225,4 +231,12 @@ public class MetadataReportConfig extends AbstractConfig {
public void setRegistry(String registry) {
this.registry = registry;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
}

View File

@ -139,15 +139,28 @@ public class MethodConfig extends AbstractMethodConfig {
this.setReturn(method.isReturn());
//TODO callback method processing is not completed
if(!"".equals(method.oninvoke())){
this.setOninvoke(method.oninvoke());
String split = ".";
if (!"".equals(method.oninvoke()) && method.oninvoke().lastIndexOf(split) > 0) {
int index = method.oninvoke().lastIndexOf(split);
String ref = method.oninvoke().substring(0, index);
String methodName = method.oninvoke().substring(index + 1);
this.setOninvoke(ref);
this.setOninvokeMethod(methodName);
}
if(!"".equals(method.onreturn())){
this.setOnreturn(method.onreturn());
if (!"".equals(method.onreturn()) && method.onreturn().lastIndexOf(split) > 0) {
int index = method.onreturn().lastIndexOf(split);
String ref = method.onreturn().substring(0, index);
String methodName = method.onreturn().substring(index + 1);
this.setOnreturn(ref);
this.setOnreturnMethod(methodName);
}
if(!"".equals(method.onthrow())){
this.setOnthrow(method.onthrow());
if (!"".equals(method.onthrow()) && method.onthrow().lastIndexOf(split) > 0) {
int index = method.onthrow().lastIndexOf(split);
String ref = method.onthrow().substring(0, index);
String methodName = method.onthrow().substring(index + 1);
this.setOnthrow(ref);
this.setOnthrowMethod(methodName);
}
if (method.arguments() != null && method.arguments().length != 0) {

View File

@ -62,11 +62,6 @@ public class ModuleConfig extends AbstractConfig {
*/
private MonitorConfig monitor;
/**
* If it's default
*/
private Boolean isDefault;
public ModuleConfig() {
}
@ -142,12 +137,4 @@ public class ModuleConfig extends AbstractConfig {
this.monitor = new MonitorConfig(monitor);
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
}

View File

@ -63,11 +63,6 @@ public class MonitorConfig extends AbstractConfig {
*/
private Map<String, String> parameters;
/**
* If it's default
*/
private Boolean isDefault;
public MonitorConfig() {
}
@ -135,14 +130,6 @@ public class MonitorConfig extends AbstractConfig {
this.parameters = parameters;
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
public String getInterval() {
return interval;
}

View File

@ -79,6 +79,11 @@ public class ProtocolConfig extends AbstractConfig {
*/
private Integer iothreads;
/**
* Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
*/
private Integer alive;
/**
* Thread pool's queue length
*/
@ -193,11 +198,6 @@ public class ProtocolConfig extends AbstractConfig {
*/
private Map<String, String> parameters;
/**
* If it's default
*/
private Boolean isDefault;
private Boolean sslEnabled;
public ProtocolConfig() {
@ -300,6 +300,14 @@ public class ProtocolConfig extends AbstractConfig {
this.iothreads = iothreads;
}
public Integer getAlive() {
return alive;
}
public void setAlive(Integer alive) {
this.alive = alive;
}
public Integer getQueues() {
return queues;
}
@ -482,14 +490,6 @@ public class ProtocolConfig extends AbstractConfig {
this.parameters = parameters;
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
@Parameter(key = SSL_ENABLED_KEY)
public Boolean getSslEnabled() {
return sslEnabled;
@ -540,4 +540,46 @@ public class ProtocolConfig extends AbstractConfig {
public boolean isValid() {
return StringUtils.isNotEmpty(name);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ProtocolConfig{");
sb.append("name='").append(name).append('\'');
sb.append(", host='").append(host).append('\'');
sb.append(", port=").append(port);
sb.append(", contextpath='").append(contextpath).append('\'');
sb.append(", threadpool='").append(threadpool).append('\'');
sb.append(", threadname='").append(threadname).append('\'');
sb.append(", corethreads=").append(corethreads);
sb.append(", threads=").append(threads);
sb.append(", iothreads=").append(iothreads);
sb.append(", alive=").append(alive);
sb.append(", queues=").append(queues);
sb.append(", accepts=").append(accepts);
sb.append(", codec='").append(codec).append('\'');
sb.append(", serialization='").append(serialization).append('\'');
sb.append(", charset='").append(charset).append('\'');
sb.append(", payload=").append(payload);
sb.append(", buffer=").append(buffer);
sb.append(", heartbeat=").append(heartbeat);
sb.append(", accesslog='").append(accesslog).append('\'');
sb.append(", transporter='").append(transporter).append('\'');
sb.append(", exchanger='").append(exchanger).append('\'');
sb.append(", dispatcher='").append(dispatcher).append('\'');
sb.append(", networker='").append(networker).append('\'');
sb.append(", server='").append(server).append('\'');
sb.append(", client='").append(client).append('\'');
sb.append(", telnet='").append(telnet).append('\'');
sb.append(", prompt='").append(prompt).append('\'');
sb.append(", status='").append(status).append('\'');
sb.append(", register=").append(register);
sb.append(", keepAlive=").append(keepAlive);
sb.append(", optimizer='").append(optimizer).append('\'');
sb.append(", extension='").append(extension).append('\'');
sb.append(", parameters=").append(parameters);
sb.append(", isDefault=").append(isDefault);
sb.append(", sslEnabled=").append(sslEnabled);
sb.append('}');
return sb.toString();
}
}

View File

@ -69,6 +69,11 @@ public class ProviderConfig extends AbstractServiceConfig {
*/
private Integer iothreads;
/**
* Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
*/
private Integer alive;
/**
* Thread pool queue length
*/
@ -149,26 +154,17 @@ public class ProviderConfig extends AbstractServiceConfig {
*/
private Integer wait;
/**
* Whether to use the default protocol
*/
private Boolean isDefault;
@Deprecated
public void setProtocol(String protocol) {
this.protocols = new ArrayList<>(Arrays.asList(new ProtocolConfig(protocol)));
}
@Override
@Parameter(excluded = true)
public Boolean isDefault() {
return isDefault;
}
@Deprecated
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
@Parameter(excluded = true)
public String getHost() {
return host;
@ -240,6 +236,14 @@ public class ProviderConfig extends AbstractServiceConfig {
this.iothreads = iothreads;
}
public Integer getAlive() {
return alive;
}
public void setAlive(Integer alive) {
this.alive = alive;
}
public Integer getQueues() {
return queues;
}
@ -425,4 +429,35 @@ public class ProviderConfig extends AbstractServiceConfig {
this.wait = wait;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ProviderConfig{");
sb.append("host='").append(host).append('\'');
sb.append(", port=").append(port);
sb.append(", contextpath='").append(contextpath).append('\'');
sb.append(", threadpool='").append(threadpool).append('\'');
sb.append(", threadname='").append(threadname).append('\'');
sb.append(", threads=").append(threads);
sb.append(", iothreads=").append(iothreads);
sb.append(", alive=").append(alive);
sb.append(", queues=").append(queues);
sb.append(", accepts=").append(accepts);
sb.append(", codec='").append(codec).append('\'');
sb.append(", charset='").append(charset).append('\'');
sb.append(", payload=").append(payload);
sb.append(", buffer=").append(buffer);
sb.append(", transporter='").append(transporter).append('\'');
sb.append(", exchanger='").append(exchanger).append('\'');
sb.append(", dispatcher='").append(dispatcher).append('\'');
sb.append(", networker='").append(networker).append('\'');
sb.append(", server='").append(server).append('\'');
sb.append(", client='").append(client).append('\'');
sb.append(", telnet='").append(telnet).append('\'');
sb.append(", prompt='").append(prompt).append('\'');
sb.append(", status='").append(status).append('\'');
sb.append(", wait=").append(wait);
sb.append(", isDefault=").append(isDefault);
sb.append('}');
return sb.toString();
}
}

View File

@ -42,11 +42,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
private static final long serialVersionUID = -5864351140409987595L;
/**
* The interface name of the reference service
*/
protected String interfaceName;
/**
* The interface class of the reference service
*/
@ -72,7 +67,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
*/
protected String protocol;
protected ServiceMetadata serviceMetadata;
public ReferenceConfigBase() {
serviceMetadata = new ServiceMetadata();
@ -268,12 +262,14 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
@Override
protected void computeValidRegistryIds() {
super.computeValidRegistryIds();
if (StringUtils.isEmpty(getRegistryIds())) {
if (getConsumer() != null && StringUtils.isNotEmpty(getConsumer().getRegistryIds())) {
setRegistryIds(getConsumer().getRegistryIds());
if (consumer != null) {
if (notHasSelfRegistryProperty()) {
setRegistries(consumer.getRegistries());
setRegistryIds(consumer.getRegistryIds());
}
}
super.computeValidRegistryIds();
}
@Parameter(excluded = true)

View File

@ -139,11 +139,6 @@ public class RegistryConfig extends AbstractConfig {
*/
private Map<String, String> parameters;
/**
* Whether it's default
*/
private Boolean isDefault;
/**
* Simple the registry. both useful for provider and consumer
*
@ -456,14 +451,6 @@ public class RegistryConfig extends AbstractConfig {
}
}
public Boolean isDefault() {
return isDefault;
}
public void setDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
public Boolean getSimplified() {
return simplified;
}

View File

@ -43,10 +43,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
private static final long serialVersionUID = 3033787999037024738L;
/**
* The interface name of the exported service
*/
protected String interfaceName;
/**
* The interface class of the exported service
@ -78,7 +75,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
*/
protected volatile String generic;
protected ServiceMetadata serviceMetadata;
public ServiceConfigBase() {
serviceMetadata = new ServiceMetadata();
@ -202,32 +199,35 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
}
public void checkProtocol() {
if (provider != null && notHasSelfProtocolProperty()) {
setProtocols(provider.getProtocols());
setProtocolIds(provider.getProtocolIds());
}
if (CollectionUtils.isEmpty(protocols) && provider != null) {
setProtocols(provider.getProtocols());
}
convertProtocolIdsToProtocols();
}
private boolean notHasSelfProtocolProperty() {
return CollectionUtils.isEmpty(protocols) && StringUtils.isEmpty(protocolIds);
}
public void completeCompoundConfigs() {
super.completeCompoundConfigs(provider);
if (provider != null) {
if (protocols == null) {
if (notHasSelfProtocolProperty()) {
setProtocols(provider.getProtocols());
setProtocolIds(provider.getProtocolIds());
}
if (configCenter == null) {
setConfigCenter(provider.getConfigCenter());
}
if (StringUtils.isEmpty(registryIds)) {
setRegistryIds(provider.getRegistryIds());
}
if (StringUtils.isEmpty(protocolIds)) {
setProtocolIds(provider.getProtocolIds());
}
}
}
private void convertProtocolIdsToProtocols() {
computeValidProtocolIds();
if (StringUtils.isEmpty(protocolIds)) {
if (CollectionUtils.isEmpty(protocols)) {
List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
@ -292,9 +292,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
setInterface(interfaceClass);
}
public String getInterface() {
return interfaceName;
}
public void setInterface(Class<?> interfaceClass) {
if (interfaceClass != null && !interfaceClass.isInterface()) {
@ -304,14 +302,6 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
setInterface(interfaceClass == null ? null : interfaceClass.getName());
}
public void setInterface(String interfaceName) {
this.interfaceName = interfaceName;
// FIXME, add id strategy in ConfigManager
// if (StringUtils.isEmpty(id)) {
// id = interfaceName;
// }
}
public T getRef() {
return ref;
}
@ -413,22 +403,14 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return StringUtils.isEmpty(this.version) ? (provider != null ? provider.getVersion() : this.version) : this.version;
}
private void computeValidProtocolIds() {
if (StringUtils.isEmpty(getProtocolIds())) {
if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getProtocolIds())) {
setProtocolIds(getProvider().getProtocolIds());
}
}
}
@Override
protected void computeValidRegistryIds() {
super.computeValidRegistryIds();
if (StringUtils.isEmpty(getRegistryIds())) {
if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getRegistryIds())) {
setRegistryIds(getProvider().getRegistryIds());
}
if (provider != null && notHasSelfRegistryProperty()) {
setRegistries(provider.getRegistries());
setRegistryIds(provider.getRegistryIds());
}
super.computeValidRegistryIds();
}
public abstract void export();

View File

@ -18,10 +18,10 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.IOUtils;
import org.apache.dubbo.config.support.Parameter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;
@ -120,9 +120,9 @@ public class SslConfig extends AbstractConfig {
this.clientTrustCertCollectionPath = clientTrustCertCollectionPath;
}
public InputStream getServerKeyCertChainPathStream() throws FileNotFoundException {
public InputStream getServerKeyCertChainPathStream() throws IOException {
if (serverKeyCertChainPath != null) {
serverKeyCertChainPathStream = new FileInputStream(serverKeyCertChainPath);
serverKeyCertChainPathStream = IOUtils.getURL(serverKeyCertChainPath).openStream();
}
return serverKeyCertChainPathStream;
}
@ -131,9 +131,9 @@ public class SslConfig extends AbstractConfig {
this.serverKeyCertChainPathStream = serverKeyCertChainPathStream;
}
public InputStream getServerPrivateKeyPathStream() throws FileNotFoundException {
public InputStream getServerPrivateKeyPathStream() throws IOException {
if (serverPrivateKeyPath != null) {
serverPrivateKeyPathStream = new FileInputStream(serverPrivateKeyPath);
serverPrivateKeyPathStream = IOUtils.getURL(serverPrivateKeyPath).openStream();
}
return serverPrivateKeyPathStream;
}
@ -142,9 +142,9 @@ public class SslConfig extends AbstractConfig {
this.serverPrivateKeyPathStream = serverPrivateKeyPathStream;
}
public InputStream getServerTrustCertCollectionPathStream() throws FileNotFoundException {
public InputStream getServerTrustCertCollectionPathStream() throws IOException {
if (serverTrustCertCollectionPath != null) {
serverTrustCertCollectionPathStream = new FileInputStream(serverTrustCertCollectionPath);
serverTrustCertCollectionPathStream = IOUtils.getURL(serverTrustCertCollectionPath).openStream();
}
return serverTrustCertCollectionPathStream;
}
@ -153,9 +153,9 @@ public class SslConfig extends AbstractConfig {
this.serverTrustCertCollectionPathStream = serverTrustCertCollectionPathStream;
}
public InputStream getClientKeyCertChainPathStream() throws FileNotFoundException {
public InputStream getClientKeyCertChainPathStream() throws IOException {
if (clientKeyCertChainPath != null) {
clientKeyCertChainPathStream = new FileInputStream(clientKeyCertChainPath);
clientKeyCertChainPathStream = IOUtils.getURL(clientKeyCertChainPath).openStream();
}
return clientKeyCertChainPathStream;
}
@ -164,9 +164,9 @@ public class SslConfig extends AbstractConfig {
this.clientKeyCertChainPathStream = clientKeyCertChainPathStream;
}
public InputStream getClientPrivateKeyPathStream() throws FileNotFoundException {
public InputStream getClientPrivateKeyPathStream() throws IOException {
if (clientPrivateKeyPath != null) {
clientPrivateKeyPathStream = new FileInputStream(clientPrivateKeyPath);
clientPrivateKeyPathStream = IOUtils.getURL(clientPrivateKeyPath).openStream();
}
return clientPrivateKeyPathStream;
}
@ -175,9 +175,9 @@ public class SslConfig extends AbstractConfig {
this.clientPrivateKeyPathStream = clientPrivateKeyPathStream;
}
public InputStream getClientTrustCertCollectionPathStream() throws FileNotFoundException {
public InputStream getClientTrustCertCollectionPathStream() throws IOException {
if (clientTrustCertCollectionPath != null) {
clientTrustCertCollectionPathStream = new FileInputStream(clientTrustCertCollectionPath);
clientTrustCertCollectionPathStream = IOUtils.getURL(clientTrustCertCollectionPath).openStream();
}
return clientTrustCertCollectionPathStream;
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.config.annotation;
import org.apache.dubbo.common.constants.ClusterRules;
import org.apache.dubbo.common.constants.LoadbalanceRules;
import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.config.ReferenceConfigBase;
@ -163,8 +165,9 @@ public @interface DubboReference {
/**
* Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
* you can use {@link org.apache.dubbo.common.constants.ClusterRules#FAIL_FAST}
*/
String cluster() default "";
String cluster() default ClusterRules.EMPTY;
/**
* Maximum connections service provider can accept, default value is 0 - connection is shared
@ -207,10 +210,9 @@ public @interface DubboReference {
/**
* Load balance strategy, legal values include: random, roundrobin, leastactive
* <p>
* see Constants#DEFAULT_LOADBALANCE
* you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM}
*/
String loadbalance() default "";
String loadbalance() default LoadbalanceRules.EMPTY;
/**
* Whether to enable async invocation, default value is false

View File

@ -17,6 +17,8 @@
package org.apache.dubbo.config.annotation;
import org.apache.dubbo.common.constants.ClusterRules;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@ -123,8 +125,9 @@ public @interface DubboService {
/**
* Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
* you can use {@link org.apache.dubbo.common.constants.ClusterRules#FAIL_FAST}
*/
String cluster() default "";
String cluster() default ClusterRules.EMPTY;
/**
* How the proxy is generated, legal values include: jdk, javassist
@ -173,9 +176,9 @@ public @interface DubboService {
/**
* Load balance strategy, legal values include: random, roundrobin, leastactive
*
* @see org.apache.dubbo.common.constants.CommonConstants#DEFAULT_LOADBALANCE
* you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM}
*/
String loadbalance() default "";
String loadbalance() default ClusterRules.EMPTY;
/**
* Whether to enable async invocation, default value is false

View File

@ -32,7 +32,7 @@ public class ConfigConfigurationAdapter implements Configuration {
public ConfigConfigurationAdapter(AbstractConfig config) {
Map<String, String> configMetadata = config.getMetaData();
metaData = new HashMap<>(configMetadata.size());
metaData = new HashMap<>(configMetadata.size(), 1.0f);
for (Map.Entry<String, String> entry : configMetadata.entrySet()) {
String prefix = config.getPrefix().endsWith(".") ? config.getPrefix() : config.getPrefix() + ".";
String id = StringUtils.isEmpty(config.getId()) ? "" : config.getId() + ".";

View File

@ -46,6 +46,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -386,9 +387,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public void clear() {
write(() -> {
this.configsCache.clear();
});
write(this.configsCache::clear);
}
/**
@ -442,6 +441,18 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
// throw new IllegalStateException("No such " + configType.getName() + " is found");
return null;
} else if (size > 1) {
AtomicReference<C> defaultConfig = new AtomicReference<>();
configsMap.forEach((str, config) -> {
if (Boolean.TRUE.equals(config.isDefault())) {
defaultConfig.compareAndSet(null, config);
}
});
if (defaultConfig.get() != null) {
return defaultConfig.get();
}
if (configWarnLogEnabled && warnLogStatus.get(configType) == null) {
logger.warn("Expected single matching of " + configType + ", but found " + size + " instances, will randomly pick the first one.");
warnLogStatus.put(configType, true);

View File

@ -23,6 +23,7 @@ package org.apache.dubbo.event;
* @since 2.7.5
*/
public final class DirectEventDispatcher extends AbstractEventDispatcher {
public static final String NAME = "direct";
public DirectEventDispatcher() {
super(DIRECT_EXECUTOR);

View File

@ -29,7 +29,7 @@ import java.util.concurrent.Executor;
* @see DirectEventDispatcher
* @since 2.7.5
*/
@SPI("direct")
@SPI(DirectEventDispatcher.NAME)
public interface EventDispatcher extends Listenable<EventListener<?>> {
/**

View File

@ -25,6 +25,7 @@ import java.util.concurrent.ForkJoinPool;
* @since 2.7.5
*/
public class ParallelEventDispatcher extends AbstractEventDispatcher {
public static final String NAME = "parallel";
public ParallelEventDispatcher() {
super(ForkJoinPool.commonPool());

View File

@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentMap;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_RAW_RETURN;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_BEAN;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_DEFAULT;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_GSON;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_NATIVE_JAVA;
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_PROTOBUF;
@ -56,6 +57,7 @@ public class ProtocolUtils {
|| GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* Streaming generalization call supporting jdk serialization */
|| GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
|| GENERIC_SERIALIZATION_PROTOBUF.equalsIgnoreCase(generic)
|| GENERIC_SERIALIZATION_GSON.equalsIgnoreCase(generic)
|| GENERIC_RAW_RETURN.equalsIgnoreCase(generic));
}
@ -75,6 +77,11 @@ public class ProtocolUtils {
&& GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic);
}
public static boolean isGsonGenericSerialization(String generic) {
return isGeneric(generic)
&& GENERIC_SERIALIZATION_GSON.equalsIgnoreCase(generic);
}
public static boolean isBeanGenericSerialization(String generic) {
return isGeneric(generic) && GENERIC_SERIALIZATION_BEAN.equals(generic);
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class BaseServiceMetadataTest {
@Test
public void test() {
BaseServiceMetadata baseServiceMetadata = new BaseServiceMetadata();
baseServiceMetadata.setGroup("group1");
baseServiceMetadata.setServiceInterfaceName("org.apache.dubbo.common.TestInterface");
baseServiceMetadata.setVersion("1.0.0");
baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", "group1", "1.0.0"));
assertEquals(baseServiceMetadata.getGroup(), "group1");
assertEquals(baseServiceMetadata.getServiceInterfaceName(), "org.apache.dubbo.common.TestInterface");
assertEquals(baseServiceMetadata.getVersion(), "1.0.0");
assertEquals(baseServiceMetadata.getServiceKey(), "group1/org.apache.dubbo.common.TestInterface:1.0.0");
assertEquals(baseServiceMetadata.getDisplayServiceKey(), "org.apache.dubbo.common.TestInterface:1.0.0");
baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", null, null));
assertEquals(baseServiceMetadata.getServiceKey(), "org.apache.dubbo.common.TestInterface");
baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", "", ""));
assertEquals(baseServiceMetadata.getServiceKey(), "org.apache.dubbo.common.TestInterface");
baseServiceMetadata.setVersion("2.0.0");
baseServiceMetadata.generateServiceKey();
assertEquals(baseServiceMetadata.getServiceKey(), "group1/org.apache.dubbo.common.TestInterface:2.0.0");
assertEquals(BaseServiceMetadata.versionFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "1.0.0");
assertEquals(BaseServiceMetadata.groupFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "group1");
assertEquals(BaseServiceMetadata.interfaceFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "org.apache.dubbo.common.TestInterface");
assertEquals(DEFAULT_VERSION, BaseServiceMetadata.versionFromServiceKey(""));
assertNull(BaseServiceMetadata.groupFromServiceKey(""));
assertEquals(BaseServiceMetadata.interfaceFromServiceKey(""), "");
assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0").getDisplayServiceKey(),
"org.apache.dubbo.common.TestInterface:1.0.0");
assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface").getDisplayServiceKey(),
"org.apache.dubbo.common.TestInterface:null");
assertEquals(BaseServiceMetadata.revertDisplayServiceKey(null).getDisplayServiceKey(),"null:null");
assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0:1").getDisplayServiceKey(),"null:null");
}
}

View File

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common;
import org.apache.dubbo.common.utils.PojoUtils;
import org.junit.jupiter.api.Test;
public class PojoUtilsForNonPublicStaticTest {
@Test
public void testNonPublicStaticClass() {
NonPublicStaticData nonPublicStaticData = new NonPublicStaticData("horizon");
PojoUtils.generalize(nonPublicStaticData);
}
/**
* the static class need is not same package with PojoUtils, so define it here.
*/
static class NonPublicStaticData {
private String name;
public NonPublicStaticData(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -16,8 +16,13 @@
*/
package org.apache.dubbo.common;
import net.bytebuddy.utility.RandomString;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
@ -25,16 +30,53 @@ import static org.hamcrest.MatcherAssert.assertThat;
* Created by LinShunkang on 2020/03/12
*/
public class URLStrParserTest {
private static Set<String> testCases = new HashSet<>(16);
private static Set<String> errorDecodedCases = new HashSet<>(8);
private static Set<String> errorEncodedCases = new HashSet<>(8);
static {
testCases.add("dubbo://192.168.1.1");
testCases.add("dubbo://192.168.1.1?");
testCases.add("dubbo://127.0.0.1?test=中文测试");
testCases.add("dubbo://admin:admin123@192.168.1.41:28113/org.test.api.DemoService$Iface?anyhost=true&application=demo-service&dubbo=2.6.1&generic=false&interface=org.test.api.DemoService$Iface&methods=orbCompare,checkText,checkPicture&pid=65557&revision=1.4.17&service.filter=bootMetrics&side=provider&status=server&threads=200&timestamp=1583136298859&version=1.0.0");
// super long text test
testCases.add("dubbo://192.168.1.1/" + RandomString.make(10240));
testCases.add("file:/path/to/file.txt");
testCases.add("dubbo://fe80:0:0:0:894:aeec:f37d:23e1%en0/path?abc=abc");
errorDecodedCases.add("dubbo:192.168.1.1");
errorDecodedCases.add("://192.168.1.1");
errorDecodedCases.add(":/192.168.1.1");
errorEncodedCases.add("dubbo%3a%2f%2f192.168.1.41%3fabc%3");
errorEncodedCases.add("dubbo%3a192.168.1.1%3fabc%3dabc");
errorEncodedCases.add("%3a%2f%2f192.168.1.1%3fabc%3dabc");
errorEncodedCases.add("%3a%2f192.168.1.1%3fabc%3dabc");
errorEncodedCases.add("dubbo%3a%2f%2f127.0.0.1%3ftest%3d%e2%96%b2%e2%96%bc%e2%97%80%e2%96%b6%e2%86%90%e2%86%91%e2%86%92%e2%86%93%e2%86%94%e2%86%95%e2%88%9e%c2%b1%e9%be%98%e9%9d%90%e9%bd%89%9%d%b");
}
@Test
public void test() {
String str = "dubbo%3A%2F%2Fadmin%3Aadmin123%40192.168.1.41%3A28113%2Forg.test.api.DemoService%24Iface%3Fanyhost%3Dtrue%26application%3Ddemo-service%26dubbo%3D2.6.1%26generic%3Dfalse%26interface%3Dorg.test.api.DemoService%24Iface%26methods%3DorbCompare%2CcheckText%2CcheckPicture%26pid%3D65557%26revision%3D1.4.17%26service.filter%3DbootMetrics%26side%3Dprovider%26status%3Dserver%26threads%3D200%26timestamp%3D1583136298859%26version%3D1.0.0";
System.out.println(URLStrParser.parseEncodedStr(str));
public void testEncoded() {
testCases.forEach(testCase -> {
assertThat(URLStrParser.parseEncodedStr(URL.encode(testCase)), equalTo(URL.valueOf(testCase)));
});
String decodeStr = URL.decode(str);
URL originalUrl = URL.valueOf(decodeStr);
assertThat(URLStrParser.parseEncodedStr(str), equalTo(originalUrl));
assertThat(URLStrParser.parseDecodedStr(decodeStr), equalTo(originalUrl));
errorEncodedCases.forEach(errorCase -> {
Assertions.assertThrows(RuntimeException.class,
() -> URLStrParser.parseEncodedStr(errorCase));
});
}
@Test
public void testDecoded() {
testCases.forEach(testCase -> {
assertThat(URLStrParser.parseDecodedStr(testCase), equalTo(URL.valueOf(testCase)));
});
errorDecodedCases.forEach(errorCase -> {
Assertions.assertThrows(RuntimeException.class,
() -> URLStrParser.parseDecodedStr(errorCase));
});
}
}

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