Migrate master bugfix (#7927)
This commit is contained in:
parent
4ea0a09846
commit
8bc9257f4e
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
## Contributing to dubbo
|
## 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.
|
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
|
### 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 contributor’s 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
|
### Contact
|
||||||
|
|
||||||
#### Mailing list
|
#### 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.
|
- [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): all the commits will be sent to this mailing list. You can subscribe to it if you are interested in Dubbo's development.
|
- [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.
|
- [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
|
### Reporting issue
|
||||||
|
|
@ -21,33 +21,33 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?templat
|
||||||
|
|
||||||
### Code Conventions
|
### 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:
|
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)
|
* 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.
|
* 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
|
### 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
|
* 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 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.
|
* 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)
|
* 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 remote add upstream git@github.com:apache/dubbo.git
|
||||||
git fetch upstream
|
git fetch upstream
|
||||||
|
|
@ -62,15 +62,15 @@ Thanks for contributing!
|
||||||
|
|
||||||
### Code style
|
### 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.
|
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 config manually by referencing the same file.
|
If you use Eclipse, you can use the IntelliJ Idea template for manually configuring your file.
|
||||||
|
|
||||||
**NOTICE**
|
**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`
|
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 .
|
2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click on .
|
||||||
From the drop-down list, select `Import Scheme`, then select this option `IntelliJ IDEA code style XML` to import scheme
|
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.
|
3. In the Scheme field, type the name of the new scheme and press ⏎ to save the changes.
|
||||||
|
|
||||||
|
|
|
||||||
2
NOTICE
2
NOTICE
|
|
@ -1,5 +1,5 @@
|
||||||
Apache Dubbo
|
Apache Dubbo
|
||||||
Copyright 2018-2020 The Apache Software Foundation
|
Copyright 2018-2021 The Apache Software Foundation
|
||||||
|
|
||||||
This product includes software developed at
|
This product includes software developed at
|
||||||
The Apache Software Foundation (http://www.apache.org/).
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
## What is the purpose of the change
|
## What is the purpose of the change
|
||||||
|
|
||||||
XXXXX
|
|
||||||
|
|
||||||
## Brief changelog
|
## Brief changelog
|
||||||
|
|
||||||
XXXXX
|
|
||||||
|
|
||||||
## Verifying this change
|
## 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.
|
- [ ] 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 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.
|
- [ ] 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.
|
||||||
|
|
|
||||||
66
README.md
66
README.md
|
|
@ -1,22 +1,22 @@
|
||||||
# Apache Dubbo Project
|
# Apache Dubbo Project
|
||||||
|
|
||||||
[](https://travis-ci.org/apache/dubbo)
|
[](https://travis-ci.com/apache/dubbo)
|
||||||
[](https://codecov.io/gh/apache/dubbo)
|
[](https://codecov.io/gh/apache/dubbo)
|
||||||

|

|
||||||

|

|
||||||
[](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
|
[](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
|
||||||
[](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
|
[](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
|
||||||
[](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://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://twitter.com/intent/follow?screen_name=ApacheDubbo)
|
[](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
|
||||||
[](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](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
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -29,14 +29,14 @@ We are now collecting dubbo user info in order to help us to improve Dubbo bette
|
||||||
|
|
||||||
## Getting started
|
## 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
|
```bash
|
||||||
# git clone https://github.com/apache/dubbo-samples.git
|
# 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
|
### Maven dependency
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ There's a [README](https://github.com/apache/dubbo-samples/tree/master/java/dubb
|
||||||
<properties>
|
<properties>
|
||||||
<dubbo.version>2.7.8</dubbo.version>
|
<dubbo.version>2.7.8</dubbo.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<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
|
### 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
|
### 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
|
### 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
|
# 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
|
```java
|
||||||
package org.apache.dubbo.samples.client;
|
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
|
### Build and run the consumer
|
||||||
|
|
||||||
|
|
@ -167,14 +167,14 @@ The consumer will print out `hi, dubbo` on the screen.
|
||||||
|
|
||||||
### Next steps
|
### 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.
|
* [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/en-us/docs/user/preface/background.html) - How to use Dubbo and all its features.
|
* [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/en-us/docs/dev/build.html) - How to involve in Dubbo development.
|
* [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/en-us/docs/admin/install/provider-demo.html) - How to admin and manage Dubbo services.
|
* [Dubbo admin manual](http://dubbo.apache.org/docs/v2.7/admin/install/provider-demo/) - How to admin and manage Dubbo services.
|
||||||
|
|
||||||
## Building
|
## 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
|
mvn clean install
|
||||||
|
|
@ -182,11 +182,11 @@ If you want to try out the cutting-edge features, you can build with the followi
|
||||||
|
|
||||||
## Contact
|
## 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)
|
* 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)
|
* 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)
|
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
@ -195,18 +195,18 @@ See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
### How can I contribute?
|
### 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).
|
* 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 mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
|
* 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).
|
* 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).
|
* Review the existing [pull request](https://github.com/apache/dubbo/pulls).
|
||||||
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
|
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
|
||||||
* blog post
|
* blog post
|
||||||
* translation on documentation
|
* 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).
|
* Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
|
||||||
* Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
|
* 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!
|
* If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
|
||||||
|
|
||||||
## Reporting bugs
|
## Reporting bugs
|
||||||
|
|
@ -215,7 +215,7 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?template
|
||||||
|
|
||||||
## Reporting a security vulnerability
|
## 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
|
## Dubbo ecosystem
|
||||||
|
|
||||||
|
|
@ -228,12 +228,12 @@ Please report security vulnerability to [us](mailto:security@dubbo.apache.org) p
|
||||||
|
|
||||||
#### Language
|
#### Language
|
||||||
|
|
||||||
|
* [Go](https://github.com/dubbo/dubbo-go) (recommended)
|
||||||
* [Node.js](https://github.com/apache/dubbo-js)
|
* [Node.js](https://github.com/apache/dubbo-js)
|
||||||
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
|
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
|
||||||
* [PHP](https://github.com/apache/dubbo-php-framework)
|
* [PHP](https://github.com/apache/dubbo-php-framework)
|
||||||
* [Go](https://github.com/dubbo/dubbo-go)
|
|
||||||
* [Erlang](https://github.com/apache/dubbo-erlang)
|
* [Erlang](https://github.com/apache/dubbo-erlang)
|
||||||
|
|
||||||
## License
|
## 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.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Supported Versions
|
## 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 |
|
| 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.
|
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, don’t 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, don’t 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.
|
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:
|
An overview of the vulnerability handling process is:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,5 +54,11 @@
|
||||||
<artifactId>zookeeper</artifactId>
|
<artifactId>zookeeper</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-serialization-hessian2</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -22,7 +22,6 @@ import org.apache.dubbo.common.extension.SPI;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cluster. (SPI, Singleton, ThreadSafe)
|
* Cluster. (SPI, Singleton, ThreadSafe)
|
||||||
|
|
@ -33,7 +32,8 @@ import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
|
||||||
*/
|
*/
|
||||||
@SPI(Cluster.DEFAULT)
|
@SPI(Cluster.DEFAULT)
|
||||||
public interface Cluster {
|
public interface Cluster {
|
||||||
String DEFAULT = FailoverCluster.NAME;
|
|
||||||
|
String DEFAULT = "failover";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge the directory invokers to a virtual invoker.
|
* Merge the directory invokers to a virtual invoker.
|
||||||
|
|
@ -56,4 +56,4 @@ public interface Cluster {
|
||||||
}
|
}
|
||||||
return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
|
return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,10 @@ public interface Constants {
|
||||||
String PEER_KEY = "peer";
|
String PEER_KEY = "peer";
|
||||||
|
|
||||||
String CONSUMER_URL_KEY = "CONSUMER_URL";
|
String CONSUMER_URL_KEY = "CONSUMER_URL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prefix of arguments router key
|
||||||
|
*/
|
||||||
|
String ARGUMENTS = "arguments";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.cluster;
|
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.URL;
|
||||||
import org.apache.dubbo.common.Version;
|
import org.apache.dubbo.common.Version;
|
||||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
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.StateRouter;
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
|
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
|
* Router chain
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,7 +87,7 @@ public class RouterChain<T> {
|
||||||
private RouterChain(URL url) {
|
private RouterChain(URL url) {
|
||||||
loopPool = executorRepository.nextExecutorExecutor();
|
loopPool = executorRepository.nextExecutorExecutor();
|
||||||
List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class)
|
List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class)
|
||||||
.getActivateExtension(url, "router");
|
.getActivateExtension(url, ROUTER_KEY);
|
||||||
|
|
||||||
List<Router> routers = extensionFactories.stream()
|
List<Router> routers = extensionFactories.stream()
|
||||||
.map(factory -> factory.getRouter(url))
|
.map(factory -> factory.getRouter(url))
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractConfigurator implements Configurator {
|
public abstract class AbstractConfigurator implements Configurator {
|
||||||
|
|
||||||
|
private static final String TILDE = "~";
|
||||||
|
|
||||||
private final URL configuratorUrl;
|
private final URL configuratorUrl;
|
||||||
|
|
||||||
public AbstractConfigurator(URL url) {
|
public AbstractConfigurator(URL url) {
|
||||||
|
|
@ -76,7 +78,8 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
String configuratorSide = configuratorUrl.getSide();
|
String configuratorSide = configuratorUrl.getSide();
|
||||||
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
|
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
|
||||||
url = configureIfMatch(NetUtils.getLocalHost(), url);
|
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);
|
url = configureIfMatch(url.getHost(), url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,10 +140,13 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
|
for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
String value = entry.getValue();
|
String value = entry.getValue();
|
||||||
if (key.startsWith("~") || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
|
boolean startWithTilde = startWithTilde(key);
|
||||||
conditionKeys.add(key);
|
if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
|
||||||
|
if (startWithTilde) {
|
||||||
|
conditionKeys.add(key);
|
||||||
|
}
|
||||||
if (value != null && !ANY_VALUE.equals(value)
|
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;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -152,6 +158,13 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
return url;
|
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);
|
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,14 @@ public class ConfigParser {
|
||||||
|
|
||||||
parseEnabled(item, config, urlBuilder);
|
parseEnabled(item, config, urlBuilder);
|
||||||
|
|
||||||
urlBuilder.append("&category=").append(DYNAMIC_CONFIGURATORS_CATEGORY);
|
|
||||||
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
||||||
|
|
||||||
List<String> apps = item.getApplications();
|
List<String> apps = item.getApplications();
|
||||||
if (CollectionUtils.isNotEmpty(apps)) {
|
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 {
|
} else {
|
||||||
urls.add(URL.valueOf(urlBuilder.toString()));
|
urls.add(URL.valueOf(urlBuilder.toString()));
|
||||||
}
|
}
|
||||||
|
|
@ -118,17 +120,18 @@ public class ConfigParser {
|
||||||
services.add("*");
|
services.add("*");
|
||||||
}
|
}
|
||||||
for (String s : services) {
|
for (String s : services) {
|
||||||
urlBuilder.append(appendService(s));
|
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
|
||||||
urlBuilder.append(toParameterString(item));
|
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);
|
tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
|
||||||
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
||||||
|
|
||||||
urls.add(URL.valueOf(urlBuilder.toString()));
|
urls.add(URL.valueOf(tmpUrlBuilder.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return urls;
|
return urls;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public interface GovernanceRuleRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* {@link #removeListener(String, String, ConfigurationListener)}
|
* {@link #removeListener(String, String, ConfigurationListener)}
|
||||||
*
|
*
|
||||||
* @param key the key to represent a configuration
|
* @param key the key to represent a configuration
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,11 @@
|
||||||
package org.apache.dubbo.rpc.cluster.loadbalance;
|
package org.apache.dubbo.rpc.cluster.loadbalance;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.common.io.Bytes;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
@ -88,7 +86,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
for (Invoker<T> invoker : invokers) {
|
for (Invoker<T> invoker : invokers) {
|
||||||
String address = invoker.getUrl().getAddress();
|
String address = invoker.getUrl().getAddress();
|
||||||
for (int i = 0; i < replicaNumber / 4; i++) {
|
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++) {
|
for (int h = 0; h < 4; h++) {
|
||||||
long m = hash(digest, h);
|
long m = hash(digest, h);
|
||||||
virtualInvokers.put(m, invoker);
|
virtualInvokers.put(m, invoker);
|
||||||
|
|
@ -99,7 +97,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
|
|
||||||
public Invoker<T> select(Invocation invocation) {
|
public Invoker<T> select(Invocation invocation) {
|
||||||
String key = toKey(invocation.getArguments());
|
String key = toKey(invocation.getArguments());
|
||||||
byte[] digest = md5(key);
|
byte[] digest = Bytes.getMD5(key);
|
||||||
return selectForKey(hash(digest, 0));
|
return selectForKey(hash(digest, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,20 +126,6 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
| (digest[number * 4] & 0xFF))
|
| (digest[number * 4] & 0xFF))
|
||||||
& 0xFFFFFFFFL;
|
& 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,20 +49,17 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
int length = invokers.size();
|
int length = invokers.size();
|
||||||
// Every invoker has the same weight?
|
// Every invoker has the same weight?
|
||||||
boolean sameWeight = true;
|
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];
|
int[] weights = new int[length];
|
||||||
// the first invoker's weight
|
|
||||||
int firstWeight = getWeight(invokers.get(0), invocation);
|
|
||||||
weights[0] = firstWeight;
|
|
||||||
// The sum of weights
|
// The sum of weights
|
||||||
int totalWeight = firstWeight;
|
int totalWeight = 0;
|
||||||
for (int i = 1; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
int weight = getWeight(invokers.get(i), invocation);
|
int weight = getWeight(invokers.get(i), invocation);
|
||||||
// save for later use
|
|
||||||
weights[i] = weight;
|
|
||||||
// Sum
|
// Sum
|
||||||
totalWeight += weight;
|
totalWeight += weight;
|
||||||
if (sameWeight && weight != firstWeight) {
|
// save for later use
|
||||||
|
weights[i] = totalWeight;
|
||||||
|
if (sameWeight && totalWeight != weight * (i + 1)) {
|
||||||
sameWeight = false;
|
sameWeight = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,8 +68,7 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
|
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
|
||||||
// Return a invoker based on the random value.
|
// Return a invoker based on the random value.
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
offset -= weights[i];
|
if (offset < weights[i]) {
|
||||||
if (offset < 0) {
|
|
||||||
return invokers.get(i);
|
return invokers.get(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.UrlUtils;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
|
import org.apache.dubbo.rpc.cluster.Constants;
|
||||||
import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
|
import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
@ -50,13 +51,18 @@ import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConditionRouter
|
* 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 class ConditionRouter extends AbstractRouter {
|
||||||
public static final String NAME = "condition";
|
public static final String NAME = "condition";
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
|
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
|
||||||
protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
|
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> whenCondition;
|
||||||
protected Map<String, MatchPair> thenCondition;
|
protected Map<String, MatchPair> thenCondition;
|
||||||
|
|
||||||
|
|
@ -65,7 +71,9 @@ public class ConditionRouter extends AbstractRouter {
|
||||||
public ConditionRouter(String rule, boolean force, boolean enabled) {
|
public ConditionRouter(String rule, boolean force, boolean enabled) {
|
||||||
this.force = force;
|
this.force = force;
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
this.init(rule);
|
if (enabled) {
|
||||||
|
this.init(rule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConditionRouter(URL url) {
|
public ConditionRouter(URL url) {
|
||||||
|
|
@ -73,7 +81,9 @@ public class ConditionRouter extends AbstractRouter {
|
||||||
this.priority = url.getParameter(PRIORITY_KEY, 0);
|
this.priority = url.getParameter(PRIORITY_KEY, 0);
|
||||||
this.force = url.getParameter(FORCE_KEY, false);
|
this.force = url.getParameter(FORCE_KEY, false);
|
||||||
this.enabled = url.getParameter(ENABLED_KEY, true);
|
this.enabled = url.getParameter(ENABLED_KEY, true);
|
||||||
init(url.getParameterAndDecoded(RULE_KEY));
|
if (enabled) {
|
||||||
|
init(url.getParameterAndDecoded(RULE_KEY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(String rule) {
|
public void init(String rule) {
|
||||||
|
|
@ -226,6 +236,16 @@ public class ConditionRouter extends AbstractRouter {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
|
for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
|
||||||
String key = matchPair.getKey();
|
String key = matchPair.getKey();
|
||||||
|
|
||||||
|
if (key.startsWith(Constants.ARGUMENTS)) {
|
||||||
|
if (!matchArguments(matchPair, invocation)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String sampleValue;
|
String sampleValue;
|
||||||
//get real invoked method name from invocation
|
//get real invoked method name from invocation
|
||||||
if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
|
if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
|
||||||
|
|
@ -258,6 +278,45 @@ public class ConditionRouter extends AbstractRouter {
|
||||||
return result;
|
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 {
|
protected static final class MatchPair {
|
||||||
final Set<String> matches = new HashSet<String>();
|
final Set<String> matches = new HashSet<String>();
|
||||||
final Set<String> mismatches = new HashSet<String>();
|
final Set<String> mismatches = new HashSet<String>();
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import org.apache.dubbo.rpc.cluster.RouterFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConditionRouterFactory
|
* ConditionRouterFactory
|
||||||
*
|
* Load when "override://" is configured {@link ConditionRouter}
|
||||||
*/
|
*/
|
||||||
public class ConditionRouterFactory implements RouterFactory {
|
public class ConditionRouterFactory implements RouterFactory {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.TagRouterRule;
|
||||||
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
|
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -160,7 +159,7 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private <T> List<Invoker<T>> filterUsingStaticTag(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
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
|
// Dynamic param
|
||||||
String tag = StringUtils.isEmpty(invocation.getAttachment(TAG_KEY)) ? url.getParameter(TAG_KEY) :
|
String tag = StringUtils.isEmpty(invocation.getAttachment(TAG_KEY)) ? url.getParameter(TAG_KEY) :
|
||||||
invocation.getAttachment(TAG_KEY);
|
invocation.getAttachment(TAG_KEY);
|
||||||
|
|
@ -188,19 +187,11 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isForceUseTag(Invocation invocation) {
|
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) {
|
private <T> List<Invoker<T>> filterInvoker(List<Invoker<T>> invokers, Predicate<Invoker<T>> predicate) {
|
||||||
boolean filter = false;
|
if (invokers.stream().allMatch(predicate)) {
|
||||||
for (int i = 0; i < invokers.size(); ++i) {
|
|
||||||
Invoker<T> invoker = invokers.get(i);
|
|
||||||
if (!predicate.test(invoker)) {
|
|
||||||
filter = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filter) {
|
|
||||||
return invokers;
|
return invokers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,8 +217,6 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
|
||||||
if ((ANYHOST_VALUE + ":" + port).equals(address)) {
|
if ((ANYHOST_VALUE + ":" + port).equals(address)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
|
logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.cluster.support;
|
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.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
|
@ -30,11 +31,13 @@ import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BroadcastClusterInvoker
|
* BroadcastClusterInvoker
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
|
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) {
|
public BroadcastClusterInvoker(Directory<T> directory) {
|
||||||
super(directory);
|
super(directory);
|
||||||
|
|
@ -47,21 +50,67 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
RpcContext.getServiceContext().setInvokers((List) invokers);
|
RpcContext.getServiceContext().setInvokers((List) invokers);
|
||||||
RpcException exception = null;
|
RpcException exception = null;
|
||||||
Result result = null;
|
Result result = null;
|
||||||
|
URL url = getUrl();
|
||||||
|
// The value range of broadcast.fail.threshold must be 0~100.
|
||||||
|
// 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) {
|
for (Invoker<T> invoker : invokers) {
|
||||||
try {
|
try {
|
||||||
result = invokeWithContext(invoker, invocation);
|
result = invokeWithContext(invoker, invocation);
|
||||||
} catch (RpcException e) {
|
if (null != result && result.hasException()) {
|
||||||
exception = e;
|
Throwable resultException = result.getException();
|
||||||
logger.warn(e.getMessage(), e);
|
if (null != resultException) {
|
||||||
|
exception = getRpcException(result.getException());
|
||||||
|
logger.warn(exception.getMessage(), exception);
|
||||||
|
if (failIndex == failThresholdIndex) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
failIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
exception = new RpcException(e.getMessage(), e);
|
exception = getRpcException(e);
|
||||||
logger.warn(e.getMessage(), e);
|
logger.warn(exception.getMessage(), exception);
|
||||||
|
if (failIndex == failThresholdIndex) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
failIndex++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exception != null) {
|
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;
|
throw exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.CORE_THREADS_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
|
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.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.GROUP_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
|
||||||
|
|
@ -90,6 +91,9 @@ public class ClusterUtils {
|
||||||
if(map.containsKey(VERSION_KEY)){
|
if(map.containsKey(VERSION_KEY)){
|
||||||
copyOfLocalMap.remove(VERSION_KEY);
|
copyOfLocalMap.remove(VERSION_KEY);
|
||||||
}
|
}
|
||||||
|
if (map.containsKey(GENERIC_KEY)) {
|
||||||
|
copyOfLocalMap.remove(GENERIC_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
copyOfLocalMap.remove(RELEASE_KEY);
|
copyOfLocalMap.remove(RELEASE_KEY);
|
||||||
copyOfLocalMap.remove(DUBBO_VERSION_KEY);
|
copyOfLocalMap.remove(DUBBO_VERSION_KEY);
|
||||||
|
|
@ -99,20 +103,22 @@ public class ClusterUtils {
|
||||||
|
|
||||||
map.putAll(copyOfLocalMap);
|
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
|
// Combine filters and listeners on Provider and Consumer
|
||||||
String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
|
String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
|
||||||
String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
|
String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
|
||||||
if (remoteFilter != null && remoteFilter.length() > 0
|
if (remoteFilter != null && remoteFilter.length() > 0
|
||||||
&& localFilter != null && localFilter.length() > 0) {
|
&& localFilter != null && localFilter.length() > 0) {
|
||||||
map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
|
map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
|
||||||
}
|
}
|
||||||
String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
|
String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
|
||||||
String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
|
String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
|
||||||
if (remoteListener != null && remoteListener.length() > 0
|
if (remoteListener != null && remoteListener.length() > 0
|
||||||
&& localListener != null && localListener.length() > 0) {
|
&& localListener != null && localListener.length() > 0) {
|
||||||
map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
|
map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,7 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
List<Invoker<T>> copyInvokers = invokers;
|
List<Invoker<T>> copyInvokers = invokers;
|
||||||
checkInvokers(copyInvokers, invocation);
|
checkInvokers(copyInvokers, invocation);
|
||||||
String methodName = RpcUtils.getMethodName(invocation);
|
String methodName = RpcUtils.getMethodName(invocation);
|
||||||
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
|
int len = calculateInvokeTimes(methodName);
|
||||||
if (len <= 0) {
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
// retry loop.
|
// retry loop.
|
||||||
RpcException le = null; // last exception.
|
RpcException le = null; // last exception.
|
||||||
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
|
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);
|
+ 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ public class MergeableClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
if (resultList.isEmpty()) {
|
if (resultList.isEmpty()) {
|
||||||
return AsyncRpcResult.newDefaultAsyncResult(invocation);
|
return AsyncRpcResult.newDefaultAsyncResult(invocation);
|
||||||
} else if (resultList.size() == 1) {
|
} else if (resultList.size() == 1) {
|
||||||
return resultList.iterator().next();
|
return AsyncRpcResult.newDefaultAsyncResult(resultList.get(0).getValue(), invocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnType == void.class) {
|
if (returnType == void.class) {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.PREFERRED_KEY;
|
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;
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_FORCE;
|
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_FORCE;
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.ZONE_KEY;
|
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) {
|
for (Invoker<T> invoker : invokers) {
|
||||||
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
|
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
|
||||||
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
|
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
|
||||||
.getParameter(REGISTRY_KEY + "." + PREFERRED_KEY, false)) {
|
.getParameter(PREFERRED_KEY, false)) {
|
||||||
return clusterInvoker.invoke(invocation);
|
return clusterInvoker.invoke(invocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +71,7 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
if (StringUtils.isNotEmpty(zone)) {
|
if (StringUtils.isNotEmpty(zone)) {
|
||||||
for (Invoker<T> invoker : invokers) {
|
for (Invoker<T> invoker : invokers) {
|
||||||
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
|
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);
|
return clusterInvoker.invoke(invocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ public abstract class AbstractCluster implements Cluster {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
|
||||||
/**
|
/**
|
||||||
* Return MockInvoker
|
* Return MockInvoker
|
||||||
* Contract:
|
* 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.
|
* if directory.list() returns more than one mock invoker, only one of them will be used.
|
||||||
*
|
*
|
||||||
* @param invocation
|
* @param invocation
|
||||||
|
|
@ -174,7 +174,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
|
||||||
if (invocation instanceof RpcInvocation) {
|
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)
|
//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());
|
((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 {
|
try {
|
||||||
invokers = directory.list(invocation);
|
invokers = directory.list(invocation);
|
||||||
} catch (RpcException e) {
|
} catch (RpcException e) {
|
||||||
|
|
|
||||||
|
|
@ -131,13 +131,7 @@ public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
|
||||||
recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
|
recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
|
||||||
recycleTimeField.setAccessible(true);
|
recycleTimeField.setAccessible(true);
|
||||||
recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
|
recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException | SecurityException 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) {
|
|
||||||
Assertions.assertTrue(true, "getField failed");
|
Assertions.assertTrue(true, "getField failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,4 +311,38 @@ public class ConditionRouterTest {
|
||||||
Assertions.assertEquals(0, filteredInvokers.size());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.Result;
|
import org.apache.dubbo.rpc.Result;
|
||||||
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
import org.apache.dubbo.rpc.RpcInvocation;
|
import org.apache.dubbo.rpc.RpcInvocation;
|
||||||
import org.apache.dubbo.rpc.cluster.Directory;
|
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()
|
@Test()
|
||||||
public void testNoInvoke() {
|
public void testNoInvoke() {
|
||||||
dic = mock(Directory.class);
|
dic = mock(Directory.class);
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@ package org.apache.dubbo.common;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2019-10-10
|
* 2019-10-10
|
||||||
*/
|
*/
|
||||||
public class BaseServiceMetadata {
|
public class BaseServiceMetadata {
|
||||||
public static final char COLON_SEPERATOR = ':';
|
public static final char COLON_SEPARATOR = ':';
|
||||||
|
|
||||||
protected String serviceKey;
|
protected String serviceKey;
|
||||||
protected String serviceInterfaceName;
|
protected String serviceInterfaceName;
|
||||||
|
|
@ -48,7 +50,7 @@ public class BaseServiceMetadata {
|
||||||
public static String versionFromServiceKey(String serviceKey) {
|
public static String versionFromServiceKey(String serviceKey) {
|
||||||
int index = serviceKey.indexOf(":");
|
int index = serviceKey.indexOf(":");
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
return null;
|
return DEFAULT_VERSION;
|
||||||
}
|
}
|
||||||
return serviceKey.substring(index + 1);
|
return serviceKey.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +79,7 @@ public class BaseServiceMetadata {
|
||||||
public String getDisplayServiceKey() {
|
public String getDisplayServiceKey() {
|
||||||
StringBuilder serviceNameBuilder = new StringBuilder();
|
StringBuilder serviceNameBuilder = new StringBuilder();
|
||||||
serviceNameBuilder.append(serviceInterfaceName);
|
serviceNameBuilder.append(serviceInterfaceName);
|
||||||
serviceNameBuilder.append(COLON_SEPERATOR).append(version);
|
serviceNameBuilder.append(COLON_SEPARATOR).append(version);
|
||||||
return serviceNameBuilder.toString();
|
return serviceNameBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +90,7 @@ public class BaseServiceMetadata {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static BaseServiceMetadata revertDisplayServiceKey(String displayKey) {
|
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) {
|
if (eles == null || eles.length < 1 || eles.length > 2) {
|
||||||
return new BaseServiceMetadata();
|
return new BaseServiceMetadata();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,9 @@ public class Parameters {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return parameters.equals(o);
|
return parameters.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import java.util.TreeMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Predicate;
|
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_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
|
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
||||||
|
|
@ -1281,7 +1281,7 @@ class URL implements Serializable {
|
||||||
return getServiceInterface();
|
return getServiceInterface();
|
||||||
}
|
}
|
||||||
return getServiceInterface() +
|
return getServiceInterface() +
|
||||||
COLON_SEPERATOR + getVersion();
|
COLON_SEPARATOR + getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ public final class URLStrParser {
|
||||||
*/
|
*/
|
||||||
public static URL parseEncodedStr(String encodedURLStr, boolean modifiable) {
|
public static URL parseEncodedStr(String encodedURLStr, boolean modifiable) {
|
||||||
Map<String, String> parameters = null;
|
Map<String, String> parameters = null;
|
||||||
int pathEndIdx = encodedURLStr.indexOf("%3F");// '?'
|
int pathEndIdx = encodedURLStr.toUpperCase().indexOf("%3F");// '?'
|
||||||
if (pathEndIdx >= 0) {
|
if (pathEndIdx >= 0) {
|
||||||
parameters = parseEncodedParams(encodedURLStr, pathEndIdx + 3);
|
parameters = parseEncodedParams(encodedURLStr, pathEndIdx + 3);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ public final class JavaBeanSerializeUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cl.newInstance();
|
return cl.getDeclaredConstructor().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getConstructorArg(Class<?> cl) {
|
public static Object getConstructorArg(Class<?> cl) {
|
||||||
|
|
|
||||||
|
|
@ -340,9 +340,7 @@ public final class ClassGenerator {
|
||||||
return mCtc.toClass(loader, pd);
|
return mCtc.toClass(loader, pd);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (NotFoundException e) {
|
} catch (NotFoundException | CannotCompileException e) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
} catch (CannotCompileException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,9 @@ public class CustomizedLoaderClassPath implements ClassPath {
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
Object cl = null;
|
Object cl = null;
|
||||||
if (clref != null)
|
if (clref != null) {
|
||||||
cl = clref.get();
|
cl = clref.get();
|
||||||
|
}
|
||||||
|
|
||||||
return cl == null ? "<null>" : cl.toString();
|
return cl == null ? "<null>" : cl.toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ public abstract class Mixin {
|
||||||
ccm.setSuperClass(Mixin.class.getName());
|
ccm.setSuperClass(Mixin.class.getName());
|
||||||
ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
|
ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
|
||||||
Class<?> mixin = ccm.toClass();
|
Class<?> mixin = ccm.toClass();
|
||||||
return (Mixin) mixin.newInstance();
|
return (Mixin) mixin.getDeclaredConstructor().newInstance();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,6 @@ public abstract class Proxy {
|
||||||
if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
|
if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ics[i].isInterface() && Modifier.isStatic(method.getModifiers())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
worked.add(desc);
|
worked.add(desc);
|
||||||
|
|
||||||
int ix = methods.size();
|
int ix = methods.size();
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,15 @@ package org.apache.dubbo.common.bytecode;
|
||||||
import org.apache.dubbo.common.utils.ClassUtils;
|
import org.apache.dubbo.common.utils.ClassUtils;
|
||||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||||
|
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtMethod;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -31,6 +35,7 @@ import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper.
|
* Wrapper.
|
||||||
|
|
@ -113,7 +118,7 @@ public abstract class Wrapper {
|
||||||
return OBJECT_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) {
|
private static Wrapper makeWrapper(Class<?> c) {
|
||||||
|
|
@ -150,10 +155,32 @@ public abstract class Wrapper {
|
||||||
pts.put(fn, ft);
|
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.
|
// get all public method.
|
||||||
boolean hasMethod = hasMethods(methods);
|
boolean hasMethod = hasMethods(methods);
|
||||||
if (hasMethod) {
|
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{");
|
c3.append(" try{");
|
||||||
for (Method m : methods) {
|
for (Method m : methods) {
|
||||||
//ignore Object's method.
|
//ignore Object's method.
|
||||||
|
|
@ -166,14 +193,8 @@ public abstract class Wrapper {
|
||||||
int len = m.getParameterTypes().length;
|
int len = m.getParameterTypes().length;
|
||||||
c3.append(" && ").append(" $3.length == ").append(len);
|
c3.append(" && ").append(" $3.length == ").append(len);
|
||||||
|
|
||||||
boolean override = false;
|
boolean overload = sameNameMethodCount.get(m.getName()) > 1;
|
||||||
for (Method m2 : methods) {
|
if (overload) {
|
||||||
if (m != m2 && m.getName().equals(m2.getName())) {
|
|
||||||
override = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (override) {
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (int l = 0; l < len; l++) {
|
for (int l = 0; l < len; l++) {
|
||||||
c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
|
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() + ".\"); }");
|
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
|
// make class
|
||||||
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
|
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
|
||||||
|
|
@ -263,7 +284,7 @@ public abstract class Wrapper {
|
||||||
for (Method m : ms.values()) {
|
for (Method m : ms.values()) {
|
||||||
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
|
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
|
||||||
}
|
}
|
||||||
return (Wrapper) wc.newInstance();
|
return (Wrapper) wc.getDeclaredConstructor().newInstance();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
|
@ -48,10 +49,8 @@ public class ClassUtils {
|
||||||
|
|
||||||
public static Object newInstance(String name) {
|
public static Object newInstance(String name) {
|
||||||
try {
|
try {
|
||||||
return forName(name).newInstance();
|
return forName(name).getDeclaredConstructor().newInstance();
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
throw new IllegalStateException(e.getMessage(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new IllegalStateException(e.getMessage(), e);
|
throw new IllegalStateException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +63,7 @@ public class ClassUtils {
|
||||||
for (String pkg : packages) {
|
for (String pkg : packages) {
|
||||||
try {
|
try {
|
||||||
return classForName(pkg + "." + className);
|
return classForName(pkg + "." + className);
|
||||||
} catch (ClassNotFoundException e2) {
|
} catch (ClassNotFoundException ignore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +122,7 @@ public class ClassUtils {
|
||||||
if (className.indexOf('.') == -1) {
|
if (className.indexOf('.') == -1) {
|
||||||
try {
|
try {
|
||||||
return arrayForName("java.lang." + className);
|
return arrayForName("java.lang." + className);
|
||||||
} catch (ClassNotFoundException e2) {
|
} catch (ClassNotFoundException ignore) {
|
||||||
// ignore, let the original exception be thrown
|
// ignore, let the original exception be thrown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +430,7 @@ public class ClassUtils {
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get simple class name from qualified class name
|
* get simple class name from qualified class name
|
||||||
*/
|
*/
|
||||||
|
|
@ -439,7 +438,6 @@ public class ClassUtils {
|
||||||
if (null == qualifiedName) {
|
if (null == qualifiedName) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = qualifiedName.lastIndexOf('.');
|
int i = qualifiedName.lastIndexOf('.');
|
||||||
return i < 0 ? qualifiedName : qualifiedName.substring(i + 1);
|
return i < 0 ? qualifiedName : qualifiedName.substring(i + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.compiler.support;
|
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.CannotCompileException;
|
||||||
import javassist.ClassPool;
|
import javassist.ClassPool;
|
||||||
import javassist.CtClass;
|
import javassist.CtClass;
|
||||||
|
|
@ -30,6 +25,11 @@ import javassist.CtNewMethod;
|
||||||
import javassist.LoaderClassPath;
|
import javassist.LoaderClassPath;
|
||||||
import javassist.NotFoundException;
|
import javassist.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CtClassBuilder is builder for CtClass
|
* CtClassBuilder is builder for CtClass
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -43,17 +43,17 @@ public class CtClassBuilder {
|
||||||
|
|
||||||
private String superClassName = "java.lang.Object";
|
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() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
|
|
@ -146,7 +146,7 @@ public class CtClassBuilder {
|
||||||
CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
|
CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
|
||||||
|
|
||||||
// add imported packages
|
// add imported packages
|
||||||
imports.stream().forEach(pool::importPackage);
|
imports.forEach(pool::importPackage);
|
||||||
|
|
||||||
// add implemented interfaces
|
// add implemented interfaces
|
||||||
for (String iface : ifaces) {
|
for (String iface : ifaces) {
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,22 @@ public class JdkCompiler extends AbstractCompiler {
|
||||||
|
|
||||||
private final JavaFileManagerImpl javaFileManager;
|
private final JavaFileManagerImpl javaFileManager;
|
||||||
|
|
||||||
private volatile List<String> options;
|
private final List<String> options;
|
||||||
|
|
||||||
public JdkCompiler() {
|
private static final String DEFAULT_JAVA_VERSION = "1.8";
|
||||||
options = new ArrayList<String>();
|
|
||||||
options.add("-source");
|
private static List<String> buildDefaultOptions(String javaVersion) {
|
||||||
options.add("1.6");
|
return Arrays.asList(
|
||||||
options.add("-target");
|
"-source", javaVersion, "-target", javaVersion
|
||||||
options.add("1.6");
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null);
|
||||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||||
if (loader instanceof URLClassLoader
|
if (loader instanceof URLClassLoader
|
||||||
|
|
@ -93,6 +101,14 @@ public class JdkCompiler extends AbstractCompiler {
|
||||||
javaFileManager = new JavaFileManagerImpl(manager, classLoader);
|
javaFileManager = new JavaFileManagerImpl(manager, classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JdkCompiler() {
|
||||||
|
this(buildDefaultOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdkCompiler(String javaVersion) {
|
||||||
|
this(buildDefaultOptions(javaVersion));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> doCompile(String name, String sourceCode) throws Throwable {
|
public Class<?> doCompile(String name, String sourceCode) throws Throwable {
|
||||||
int i = name.lastIndexOf('.');
|
int i = name.lastIndexOf('.');
|
||||||
|
|
@ -102,7 +118,7 @@ public class JdkCompiler extends AbstractCompiler {
|
||||||
javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
|
javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
|
||||||
className + ClassUtils.JAVA_EXTENSION, javaFileObject);
|
className + ClassUtils.JAVA_EXTENSION, javaFileObject);
|
||||||
Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
|
Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
|
||||||
null, Arrays.asList(javaFileObject)).call();
|
null, Collections.singletonList(javaFileObject)).call();
|
||||||
if (result == null || !result) {
|
if (result == null || !result) {
|
||||||
throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
|
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>();
|
private final Map<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeConfig(String key, String group) {
|
public boolean removeConfig(String key, String group) {
|
||||||
return execute(() -> doRemoveConfig(key, group), -1L);
|
return Boolean.TRUE.equals(execute(() -> doRemoveConfig(key, group), -1L));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,12 @@ public class ConfigChangedEvent extends EventObject {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof ConfigChangedEvent)) return false;
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof ConfigChangedEvent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ConfigChangedEvent that = (ConfigChangedEvent) o;
|
ConfigChangedEvent that = (ConfigChangedEvent) o;
|
||||||
return Objects.equals(getKey(), that.getKey()) &&
|
return Objects.equals(getKey(), that.getKey()) &&
|
||||||
Objects.equals(getGroup(), that.getGroup()) &&
|
Objects.equals(getGroup(), that.getGroup()) &&
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.config.configcenter;
|
package org.apache.dubbo.common.config.configcenter;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public interface Constants {
|
public interface Constants {
|
||||||
String CONFIG_CLUSTER_KEY = "config.cluster";
|
String CONFIG_CLUSTER_KEY = "config.cluster";
|
||||||
String CONFIG_NAMESPACE_KEY = "config.namespace";
|
String CONFIG_NAMESPACE_KEY = "config.namespace";
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.TreeSet;
|
||||||
|
|
||||||
import static java.util.Collections.emptySortedSet;
|
import static java.util.Collections.emptySortedSet;
|
||||||
import static java.util.Collections.unmodifiableSortedSet;
|
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.constants.CommonConstants.PATH_SEPARATOR;
|
||||||
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
|
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
|
||||||
import static org.apache.dubbo.common.utils.PathUtils.buildPath;
|
import static org.apache.dubbo.common.utils.PathUtils.buildPath;
|
||||||
|
|
@ -87,7 +87,7 @@ public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfig
|
||||||
@Override
|
@Override
|
||||||
public final boolean publishConfig(String key, String group, String content) {
|
public final boolean publishConfig(String key, String group, String content) {
|
||||||
String pathKey = buildPathKey(group, key);
|
String pathKey = buildPathKey(group, key);
|
||||||
return execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout());
|
return Boolean.TRUE.equals(execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -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 = "";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -114,6 +114,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String IO_THREADS_KEY = "iothreads";
|
String IO_THREADS_KEY = "iothreads";
|
||||||
|
|
||||||
|
String KEEP_ALIVE_KEY = "keep.alive";
|
||||||
|
|
||||||
int DEFAULT_QUEUES = 0;
|
int DEFAULT_QUEUES = 0;
|
||||||
|
|
||||||
int DEFAULT_ALIVE = 60 * 1000;
|
int DEFAULT_ALIVE = 60 * 1000;
|
||||||
|
|
@ -207,6 +209,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String REMOTE_METADATA_STORAGE_TYPE = "remote";
|
String REMOTE_METADATA_STORAGE_TYPE = "remote";
|
||||||
|
|
||||||
|
String GENERIC_KEY = "generic";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
|
* The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
|
||||||
* {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
|
* {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
|
||||||
|
|
@ -248,6 +252,11 @@ public interface CommonConstants {
|
||||||
String PORT_KEY = "port";
|
String PORT_KEY = "port";
|
||||||
String DUBBO_IP_TO_BIND = "DUBBO_IP_TO_BIND";
|
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 property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
|
||||||
* the Dubbo application prefers
|
* the Dubbo application prefers
|
||||||
|
|
@ -311,6 +320,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
|
String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
|
||||||
|
|
||||||
|
String GENERIC_SERIALIZATION_GSON = "gson";
|
||||||
|
|
||||||
String GENERIC_SERIALIZATION_DEFAULT = "true";
|
String GENERIC_SERIALIZATION_DEFAULT = "true";
|
||||||
|
|
||||||
String GENERIC_SERIALIZATION_BEAN = "bean";
|
String GENERIC_SERIALIZATION_BEAN = "bean";
|
||||||
|
|
@ -401,4 +412,9 @@ public interface CommonConstants {
|
||||||
String CLUSTER_INTERCEPTOR_COMPATIBLE_KEY = "dubbo.application.cluster.interceptor.compatible";
|
String CLUSTER_INTERCEPTOR_COMPATIBLE_KEY = "dubbo.application.cluster.interceptor.compatible";
|
||||||
|
|
||||||
String UTF8ENCODE = "UTF-8";
|
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";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 = "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -114,6 +114,11 @@ public class ExtensionLoader<T> {
|
||||||
|
|
||||||
private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();
|
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) {
|
public static void setLoadingStrategies(LoadingStrategy... strategies) {
|
||||||
if (ArrayUtils.isNotEmpty(strategies)) {
|
if (ArrayUtils.isNotEmpty(strategies)) {
|
||||||
ExtensionLoader.strategies = strategies;
|
ExtensionLoader.strategies = strategies;
|
||||||
|
|
@ -624,26 +629,25 @@ public class ExtensionLoader<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private IllegalStateException findException(String name) {
|
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);
|
StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name);
|
||||||
|
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
|
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
|
||||||
if (i == 1) {
|
if (entry.getKey().toLowerCase().startsWith(name.toLowerCase())) {
|
||||||
buf.append(", possible causes: ");
|
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(");
|
if (i == 1) {
|
||||||
buf.append(i++);
|
buf.append(", no related exception was found, please check whether related SPI module is missing.");
|
||||||
buf.append(") ");
|
|
||||||
buf.append(entry.getKey());
|
|
||||||
buf.append(":\r\n");
|
|
||||||
buf.append(StringUtils.toString(entry.getValue()));
|
|
||||||
}
|
}
|
||||||
return new IllegalStateException(buf.toString());
|
return new IllegalStateException(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
@ -651,13 +655,13 @@ public class ExtensionLoader<T> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private T createExtension(String name, boolean wrap) {
|
private T createExtension(String name, boolean wrap) {
|
||||||
Class<?> clazz = getExtensionClasses().get(name);
|
Class<?> clazz = getExtensionClasses().get(name);
|
||||||
if (clazz == null) {
|
if (clazz == null || unacceptableExceptions.contains(name)) {
|
||||||
throw findException(name);
|
throw findException(name);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
T instance = (T) EXTENSION_INSTANCES.get(clazz);
|
T instance = (T) EXTENSION_INSTANCES.get(clazz);
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
|
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
|
||||||
instance = (T) EXTENSION_INSTANCES.get(clazz);
|
instance = (T) EXTENSION_INSTANCES.get(clazz);
|
||||||
}
|
}
|
||||||
injectExtension(instance);
|
injectExtension(instance);
|
||||||
|
|
@ -872,6 +876,7 @@ public class ExtensionLoader<T> {
|
||||||
try {
|
try {
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
|
||||||
String line;
|
String line;
|
||||||
|
String clazz = null;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
final int ci = line.indexOf('#');
|
final int ci = line.indexOf('#');
|
||||||
if (ci >= 0) {
|
if (ci >= 0) {
|
||||||
|
|
@ -884,10 +889,12 @@ public class ExtensionLoader<T> {
|
||||||
int i = line.indexOf('=');
|
int i = line.indexOf('=');
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
name = line.substring(0, i).trim();
|
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)) {
|
if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
|
||||||
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden);
|
loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), 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) {
|
if (c == null || overridden) {
|
||||||
extensionClasses.put(name, clazz);
|
extensionClasses.put(name, clazz);
|
||||||
} else if (c != 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();
|
String duplicateMsg = "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
|
||||||
logger.error(duplicateMsg);
|
logger.error(duplicateMsg);
|
||||||
throw new IllegalStateException(duplicateMsg);
|
throw new IllegalStateException(duplicateMsg);
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.extension;
|
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.
|
* The annotated class will only work as a wrapper when the condition matches.
|
||||||
*/
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Wrapper {
|
public @interface Wrapper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -259,9 +259,7 @@ class J2oVisitor implements JSONVisitor {
|
||||||
try {
|
try {
|
||||||
mValue = mType.newInstance();
|
mValue = mType.newInstance();
|
||||||
mWrapper = Wrapper.getWrapper(mType);
|
mWrapper = Wrapper.getWrapper(mType);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException | InstantiationException e) {
|
||||||
throw new ParseException(StringUtils.toString(e));
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
throw new ParseException(StringUtils.toString(e));
|
throw new ParseException(StringUtils.toString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -304,9 +302,7 @@ class J2oVisitor implements JSONVisitor {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
}
|
}
|
||||||
field.set(mValue, obj);
|
field.set(mValue, obj);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
throw new ParseException(StringUtils.toString(e));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ParseException(StringUtils.toString(e));
|
throw new ParseException(StringUtils.toString(e));
|
||||||
}
|
}
|
||||||
} else if (!CLASS_PROPERTY.equals(name)) {
|
} else if (!CLASS_PROPERTY.equals(name)) {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public interface Prioritized extends Comparable<Prioritized> {
|
||||||
/**
|
/**
|
||||||
* Get the priority
|
* Get the priority
|
||||||
*
|
*
|
||||||
* @return the default is {@link #MIN_PRIORITY minimum one}
|
* @return the default is {@link #NORMAL_PRIORITY}
|
||||||
*/
|
*/
|
||||||
default int getPriority() {
|
default int getPriority() {
|
||||||
return NORMAL_PRIORITY;
|
return NORMAL_PRIORITY;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ public class InternalThreadLocal<V> {
|
||||||
if (v != null && v != InternalThreadLocalMap.UNSET) {
|
if (v != null && v != InternalThreadLocalMap.UNSET) {
|
||||||
Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
|
Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
|
||||||
InternalThreadLocal<?>[] variablesToRemoveArray =
|
InternalThreadLocal<?>[] variablesToRemoveArray =
|
||||||
variablesToRemove.toArray(new InternalThreadLocal[variablesToRemove.size()]);
|
variablesToRemove.toArray(new InternalThreadLocal[0]);
|
||||||
for (InternalThreadLocal<?> tlv : variablesToRemoveArray) {
|
for (InternalThreadLocal<?> tlv : variablesToRemoveArray) {
|
||||||
tlv.remove(threadLocalMap);
|
tlv.remove(threadLocalMap);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ public class NamedInternalThreadFactory extends NamedThreadFactory {
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable runnable) {
|
public Thread newThread(Runnable runnable) {
|
||||||
String name = mPrefix + mThreadNum.getAndIncrement();
|
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);
|
ret.setDaemon(mDaemon);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
* The most important difference between this Executor and other normal Executor is that this one doesn't manage
|
||||||
* any thread.
|
* 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.
|
* 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
|
* 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.
|
* is exactly the same as the one calling waitAndDrain.
|
||||||
|
|
@ -86,7 +86,13 @@ public class ThreadlessExecutor extends AbstractExecutorService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Runnable runnable = queue.take();
|
Runnable runnable;
|
||||||
|
try {
|
||||||
|
runnable = queue.take();
|
||||||
|
}catch (InterruptedException e){
|
||||||
|
waiting = false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
waiting = false;
|
waiting = false;
|
||||||
|
|
@ -95,12 +101,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
|
||||||
|
|
||||||
runnable = queue.poll();
|
runnable = queue.poll();
|
||||||
while (runnable != null) {
|
while (runnable != null) {
|
||||||
try {
|
runnable.run();
|
||||||
runnable.run();
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.info(t);
|
|
||||||
|
|
||||||
}
|
|
||||||
runnable = queue.poll();
|
runnable = queue.poll();
|
||||||
}
|
}
|
||||||
// mark the status of ThreadlessExecutor as finished.
|
// mark the status of ThreadlessExecutor as finished.
|
||||||
|
|
@ -131,6 +132,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable runnable) {
|
public void execute(Runnable runnable) {
|
||||||
|
runnable = new RunnableWrapper(runnable);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (!waiting) {
|
if (!waiting) {
|
||||||
sharedExecutor.execute(runnable);
|
sharedExecutor.execute(runnable);
|
||||||
|
|
@ -180,4 +182,21 @@ public class ThreadlessExecutor extends AbstractExecutorService {
|
||||||
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.threadpool.support;
|
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.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
@ -26,13 +34,7 @@ import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import static java.lang.String.format;
|
||||||
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 org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
|
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 Semaphore guard = new Semaphore(1);
|
||||||
|
|
||||||
|
private static final String USER_HOME = System.getProperty("user.home");
|
||||||
|
|
||||||
public AbortPolicyWithReport(String threadName, URL url) {
|
public AbortPolicyWithReport(String threadName, URL url) {
|
||||||
this.threadName = threadName;
|
this.threadName = threadName;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
@ -104,7 +108,7 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
|
||||||
|
|
||||||
ExecutorService pool = Executors.newSingleThreadExecutor();
|
ExecutorService pool = Executors.newSingleThreadExecutor();
|
||||||
pool.execute(() -> {
|
pool.execute(() -> {
|
||||||
String dumpPath = url.getParameter(DUMP_DIRECTORY, System.getProperty("user.home"));
|
String dumpPath = getDumpPath();
|
||||||
|
|
||||||
SimpleDateFormat sdf;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -805,8 +805,10 @@ public class HashedWheelTimer implements Timer {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final boolean IS_OS_WINDOWS = System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
|
||||||
|
|
||||||
private boolean isWindows() {
|
private boolean isWindows() {
|
||||||
return System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
|
return IS_OS_WINDOWS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.DEFAULT_KEY_PREFIX;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
|
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}
|
* 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`.
|
* Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
|
||||||
*
|
*
|
||||||
* @param method method name
|
* @param method method name
|
||||||
* @param key key
|
* @param key key
|
||||||
* @return value
|
* @return value
|
||||||
*/
|
*/
|
||||||
public String getMethodParameter(String method, String key) {
|
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`.
|
* Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
|
||||||
*
|
*
|
||||||
* @param method method name
|
* @param method method name
|
||||||
* @param key key
|
* @param key key
|
||||||
* @return value
|
* @return value
|
||||||
*/
|
*/
|
||||||
public String getMethodParameterStrict(String method, String key) {
|
public String getMethodParameterStrict(String method, String key) {
|
||||||
|
|
@ -853,10 +854,27 @@ public class URLParam implements Serializable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
URLParam urlParam = (URLParam) o;
|
URLParam urlParam = (URLParam) o;
|
||||||
return Objects.equals(KEY, urlParam.KEY)
|
|
||||||
|
if (Objects.equals(KEY, urlParam.KEY)
|
||||||
&& Objects.equals(DEFAULT_KEY, urlParam.DEFAULT_KEY)
|
&& Objects.equals(DEFAULT_KEY, urlParam.DEFAULT_KEY)
|
||||||
&& Arrays.equals(VALUE, urlParam.VALUE)
|
&& Arrays.equals(VALUE, urlParam.VALUE)) {
|
||||||
&& Objects.equals(EXTRA_PARAMS, urlParam.EXTRA_PARAMS);
|
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;
|
private int hashCodeCache = -1;
|
||||||
|
|
@ -864,7 +882,11 @@ public class URLParam implements Serializable {
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (hashCodeCache == -1) {
|
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) {
|
for (Integer value : VALUE) {
|
||||||
hashCodeCache = hashCodeCache * 31 + value;
|
hashCodeCache = hashCodeCache * 31 + value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
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.getAllInheritedTypes;
|
||||||
import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
|
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.CollectionUtils.first;
|
||||||
|
import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
|
||||||
import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
|
import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -449,4 +451,32 @@ public interface AnnotationUtils {
|
||||||
Class<? extends Annotation>... annotationTypes) {
|
Class<? extends Annotation>... annotationTypes) {
|
||||||
return isAnnotationPresent(type, false, 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,4 +66,16 @@ public final class ArrayUtils {
|
||||||
return -1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,21 +43,6 @@ public class ClassUtils {
|
||||||
* Suffix for array class names: "[]"
|
* Suffix for array class names: "[]"
|
||||||
*/
|
*/
|
||||||
public static final String ARRAY_SUFFIX = "[]";
|
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:
|
* Simple Types including:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
|
@ -94,7 +79,20 @@ public class ClassUtils {
|
||||||
Date.class,
|
Date.class,
|
||||||
Object.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 = '.';
|
private static final char PACKAGE_SEPARATOR_CHAR = '.';
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
||||||
|
|
@ -39,28 +39,25 @@ import static java.util.Collections.unmodifiableSet;
|
||||||
*/
|
*/
|
||||||
public class CollectionUtils {
|
public class CollectionUtils {
|
||||||
|
|
||||||
private static final Comparator<String> SIMPLE_NAME_COMPARATOR = new Comparator<String>() {
|
private static final Comparator<String> SIMPLE_NAME_COMPARATOR = (s1, s2) -> {
|
||||||
@Override
|
if (s1 == null && s2 == null) {
|
||||||
public int compare(String s1, String s2) {
|
return 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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() {
|
private CollectionUtils() {
|
||||||
|
|
@ -324,9 +321,7 @@ public class CollectionUtils {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return one.containsAll(another);
|
return one.containsAll(another);
|
||||||
} catch (ClassCastException unused) {
|
} catch (ClassCastException | NullPointerException unused) {
|
||||||
return false;
|
|
||||||
} catch (NullPointerException unused) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -111,17 +112,23 @@ public class CompatibleTypeUtils {
|
||||||
+ DATE_FORMAT + ", cause: " + e.getMessage(), e);
|
+ DATE_FORMAT + ", cause: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class
|
if (type == java.time.LocalDateTime.class) {
|
||||||
|| type == java.time.LocalTime.class) {
|
if (StringUtils.isEmpty(string)) {
|
||||||
|
return null;
|
||||||
LocalDateTime localDateTime = LocalDateTime.parse(string);
|
|
||||||
if (type == java.time.LocalDate.class) {
|
|
||||||
return localDateTime.toLocalDate();
|
|
||||||
}
|
}
|
||||||
if (type == java.time.LocalTime.class) {
|
return LocalDateTime.parse(string);
|
||||||
return localDateTime.toLocalTime();
|
}
|
||||||
|
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) {
|
if (type == Class.class) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -200,19 +207,19 @@ public class CompatibleTypeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {
|
if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {
|
||||||
|
int length = Array.getLength(value);
|
||||||
Collection collection;
|
Collection collection;
|
||||||
if (!type.isInterface()) {
|
if (!type.isInterface()) {
|
||||||
try {
|
try {
|
||||||
collection = (Collection) type.newInstance();
|
collection = (Collection) type.newInstance();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
collection = new ArrayList<Object>();
|
collection = new ArrayList<Object>(length);
|
||||||
}
|
}
|
||||||
} else if (type == Set.class) {
|
} else if (type == Set.class) {
|
||||||
collection = new HashSet<Object>();
|
collection = new HashSet<Object>(Math.max((int) (length/.75f) + 1, 16));
|
||||||
} else {
|
} else {
|
||||||
collection = new ArrayList<Object>();
|
collection = new ArrayList<Object>(length);
|
||||||
}
|
}
|
||||||
int length = Array.getLength(value);
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
collection.add(Array.get(value, i));
|
collection.add(Array.get(value, i));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,7 @@ public class ExecutorUtil {
|
||||||
try {
|
try {
|
||||||
// Disable new tasks from being submitted
|
// Disable new tasks from being submitted
|
||||||
es.shutdown();
|
es.shutdown();
|
||||||
} catch (SecurityException ex2) {
|
} catch (SecurityException | NullPointerException ex2) {
|
||||||
return;
|
|
||||||
} catch (NullPointerException ex2) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -86,9 +84,7 @@ public class ExecutorUtil {
|
||||||
final ExecutorService es = (ExecutorService) executor;
|
final ExecutorService es = (ExecutorService) executor;
|
||||||
try {
|
try {
|
||||||
es.shutdownNow();
|
es.shutdownNow();
|
||||||
} catch (SecurityException ex2) {
|
} catch (SecurityException | NullPointerException ex2) {
|
||||||
return;
|
|
||||||
} catch (NullPointerException ex2) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ public interface FieldUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalStateException(String.format("cannot find field %s,field is null", fieldName));
|
||||||
|
}
|
||||||
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,12 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.utils;
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
@ -30,6 +33,8 @@ import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -228,4 +233,38 @@ public class IOUtils {
|
||||||
writeLines(new FileOutputStream(file, true), lines);
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,12 +30,12 @@ public class LFUCache<K, V> {
|
||||||
private int curSize = 0;
|
private int curSize = 0;
|
||||||
|
|
||||||
private final ReentrantLock lock = new ReentrantLock();
|
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() {
|
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 maxCapacity cache max capacity
|
||||||
* @param evictionFactor cache proceedEviction factor
|
* @param evictionFactor cache proceedEviction factor
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public LFUCache(final int maxCapacity, final float evictionFactor) {
|
public LFUCache(final int maxCapacity, final float evictionFactor) {
|
||||||
if (maxCapacity <= 0) {
|
if (maxCapacity <= 0) {
|
||||||
throw new IllegalArgumentException("Illegal initial capacity: " +
|
throw new IllegalArgumentException("Illegal initial capacity: " +
|
||||||
maxCapacity);
|
maxCapacity);
|
||||||
}
|
}
|
||||||
boolean factorInRange = evictionFactor <= 1 || evictionFactor < 0;
|
boolean factorInRange = evictionFactor <= 1 && evictionFactor > 0;
|
||||||
if (!factorInRange || Float.isNaN(evictionFactor)) {
|
if (!factorInRange || Float.isNaN(evictionFactor)) {
|
||||||
throw new IllegalArgumentException("Illegal eviction factor value:"
|
throw new IllegalArgumentException("Illegal eviction factor value:"
|
||||||
+ evictionFactor);
|
+ evictionFactor);
|
||||||
|
|
@ -61,7 +62,7 @@ public class LFUCache<K, V> {
|
||||||
this.map = new HashMap<>();
|
this.map = new HashMap<>();
|
||||||
this.freqTable = new CacheDeque[capacity + 1];
|
this.freqTable = new CacheDeque[capacity + 1];
|
||||||
for (int i = 0; i <= capacity; i++) {
|
for (int i = 0; i <= capacity; i++) {
|
||||||
freqTable[i] = new CacheDeque<K, V>();
|
freqTable[i] = new CacheDeque<>();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < capacity; i++) {
|
for (int i = 0; i < capacity; i++) {
|
||||||
freqTable[i].nextDeque = freqTable[i + 1];
|
freqTable[i].nextDeque = freqTable[i + 1];
|
||||||
|
|
@ -77,11 +78,9 @@ public class LFUCache<K, V> {
|
||||||
CacheNode<K, V> node;
|
CacheNode<K, V> node;
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
if (map.containsKey(key)) {
|
node = map.get(key);
|
||||||
node = map.get(key);
|
if (node != null) {
|
||||||
if (node != null) {
|
CacheNode.withdrawNode(node);
|
||||||
CacheNode.withdrawNode(node);
|
|
||||||
}
|
|
||||||
node.value = value;
|
node.value = value;
|
||||||
freqTable[0].addLastNode(node);
|
freqTable[0].addLastNode(node);
|
||||||
map.put(key, node);
|
map.put(key, node);
|
||||||
|
|
@ -171,7 +170,7 @@ public class LFUCache<K, V> {
|
||||||
CacheNode<K, V> next;
|
CacheNode<K, V> next;
|
||||||
K key;
|
K key;
|
||||||
V value;
|
V value;
|
||||||
CacheDeque owner;
|
CacheDeque<K, V> owner;
|
||||||
|
|
||||||
CacheNode() {
|
CacheNode() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.MemberUtils.isStatic;
|
||||||
import static org.apache.dubbo.common.utils.ReflectUtils.EMPTY_CLASS_ARRAY;
|
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.ReflectUtils.resolveTypes;
|
||||||
|
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Miscellaneous method utility methods.
|
* Miscellaneous method utility methods.
|
||||||
|
|
@ -50,7 +51,7 @@ public interface MethodUtils {
|
||||||
* @param method the method to check
|
* @param method the method to check
|
||||||
* @return whether the given method is setter method
|
* @return whether the given method is setter method
|
||||||
*/
|
*/
|
||||||
public static boolean isSetter(Method method) {
|
static boolean isSetter(Method method) {
|
||||||
return method.getName().startsWith("set")
|
return method.getName().startsWith("set")
|
||||||
&& !"set".equals(method.getName())
|
&& !"set".equals(method.getName())
|
||||||
&& Modifier.isPublic(method.getModifiers())
|
&& Modifier.isPublic(method.getModifiers())
|
||||||
|
|
@ -65,7 +66,7 @@ public interface MethodUtils {
|
||||||
* @param method the method to check
|
* @param method the method to check
|
||||||
* @return whether the given method is getter method
|
* @return whether the given method is getter method
|
||||||
*/
|
*/
|
||||||
public static boolean isGetter(Method method) {
|
static boolean isGetter(Method method) {
|
||||||
String name = method.getName();
|
String name = method.getName();
|
||||||
return (name.startsWith("get") || name.startsWith("is"))
|
return (name.startsWith("get") || name.startsWith("is"))
|
||||||
&& !"get".equals(name) && !"is".equals(name)
|
&& !"get".equals(name) && !"is".equals(name)
|
||||||
|
|
@ -82,7 +83,7 @@ public interface MethodUtils {
|
||||||
* @param method the method to check
|
* @param method the method to check
|
||||||
* @return whether the given method is meta method
|
* @return whether the given method is meta method
|
||||||
*/
|
*/
|
||||||
public static boolean isMetaMethod(Method method) {
|
static boolean isMetaMethod(Method method) {
|
||||||
String name = method.getName();
|
String name = method.getName();
|
||||||
if (!(name.startsWith("get") || name.startsWith("is"))) {
|
if (!(name.startsWith("get") || name.startsWith("is"))) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -113,12 +114,11 @@ public interface MethodUtils {
|
||||||
* @param method the method to check
|
* @param method the method to check
|
||||||
* @return whether the given method is deprecated method
|
* @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;
|
return method.getAnnotation(Deprecated.class) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link Predicate} for {@link Method} to exclude the specified declared class
|
* 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) {
|
static Method findMethod(Class type, String methodName, Class<?>... parameterTypes) {
|
||||||
Method method = null;
|
Method method = null;
|
||||||
try {
|
try {
|
||||||
method = type.getDeclaredMethod(methodName, parameterTypes);
|
if (type != null && isNotEmpty(methodName)) {
|
||||||
|
method = type.getDeclaredMethod(methodName, parameterTypes);
|
||||||
|
}
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
}
|
}
|
||||||
return method;
|
return method;
|
||||||
|
|
@ -274,6 +276,10 @@ public interface MethodUtils {
|
||||||
Method method = findMethod(type, methodName, parameterTypes);
|
Method method = findMethod(type, methodName, parameterTypes);
|
||||||
T value = null;
|
T value = null;
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
throw new IllegalStateException(String.format("cannot find method %s,class: %s", methodName, type.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final boolean isAccessible = method.isAccessible();
|
final boolean isAccessible = method.isAccessible();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,9 @@ public class NetUtils {
|
||||||
return configIp;
|
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 {
|
public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
|
||||||
boolean interfaceSet = false;
|
boolean interfaceSet = false;
|
||||||
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
|
for (NetworkInterface networkInterface : getValidNetworkInterfaces()) {
|
||||||
while (interfaces.hasMoreElements()) {
|
Enumeration addresses = networkInterface.getInetAddresses();
|
||||||
NetworkInterface i = (NetworkInterface) interfaces.nextElement();
|
|
||||||
Enumeration addresses = i.getInetAddresses();
|
|
||||||
while (addresses.hasMoreElements()) {
|
while (addresses.hasMoreElements()) {
|
||||||
InetAddress address = (InetAddress) addresses.nextElement();
|
InetAddress address = (InetAddress) addresses.nextElement();
|
||||||
if (preferIpv6 && address instanceof Inet6Address) {
|
if (preferIpv6 && address instanceof Inet6Address) {
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ public class PojoUtils {
|
||||||
}
|
}
|
||||||
for (Method method : pojo.getClass().getMethods()) {
|
for (Method method : pojo.getClass().getMethods()) {
|
||||||
if (ReflectUtils.isBeanPropertyReadMethod(method)) {
|
if (ReflectUtils.isBeanPropertyReadMethod(method)) {
|
||||||
|
ReflectUtils.makeAccessible(method);
|
||||||
try {
|
try {
|
||||||
map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));
|
map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -588,11 +589,7 @@ public class PojoUtils {
|
||||||
constructor.setAccessible(true);
|
constructor.setAccessible(true);
|
||||||
Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray();
|
Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray();
|
||||||
return constructor.newInstance(parameters);
|
return constructor.newInstance(parameters);
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -608,9 +605,15 @@ public class PojoUtils {
|
||||||
if ("char".equals(parameterType.getName())) {
|
if ("char".equals(parameterType.getName())) {
|
||||||
return Character.MIN_VALUE;
|
return Character.MIN_VALUE;
|
||||||
}
|
}
|
||||||
if ("bool".equals(parameterType.getName())) {
|
if ("boolean".equals(parameterType.getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ("byte".equals(parameterType.getName())) {
|
||||||
|
return (byte) 0;
|
||||||
|
}
|
||||||
|
if ("short".equals(parameterType.getName())) {
|
||||||
|
return (short) 0;
|
||||||
|
}
|
||||||
return parameterType.isPrimitive() ? 0 : null;
|
return parameterType.isPrimitive() ? 0 : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.CodeSource;
|
import java.security.CodeSource;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
|
@ -154,8 +155,8 @@ public final class ReflectUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPrimitives(Class<?> cls) {
|
public static boolean isPrimitives(Class<?> cls) {
|
||||||
if (cls.isArray()) {
|
while (cls.isArray()) {
|
||||||
return isPrimitive(cls.getComponentType());
|
cls = cls.getComponentType();
|
||||||
}
|
}
|
||||||
return isPrimitive(cls);
|
return isPrimitive(cls);
|
||||||
}
|
}
|
||||||
|
|
@ -904,7 +905,9 @@ public final class ReflectUtils {
|
||||||
* @throws NoSuchMethodException
|
* @throws NoSuchMethodException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
* @throws IllegalStateException when multiple methods are found (overridden method when parameter info is not provided)
|
* @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)
|
public static Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes)
|
||||||
throws NoSuchMethodException, ClassNotFoundException {
|
throws NoSuchMethodException, ClassNotFoundException {
|
||||||
String signature = clazz.getName() + "." + methodName;
|
String signature = clazz.getName() + "." + methodName;
|
||||||
|
|
@ -943,6 +946,16 @@ public final class ReflectUtils {
|
||||||
return method;
|
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)
|
public static Method findMethodByMethodName(Class<?> clazz, String methodName)
|
||||||
throws NoSuchMethodException, ClassNotFoundException {
|
throws NoSuchMethodException, ClassNotFoundException {
|
||||||
return findMethodByMethodSignature(clazz, methodName, null);
|
return findMethodByMethodSignature(clazz, methodName, null);
|
||||||
|
|
@ -1051,7 +1064,7 @@ public final class ReflectUtils {
|
||||||
try {
|
try {
|
||||||
Object value = emptyInstances.get(returnType);
|
Object value = emptyInstances.get(returnType);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = returnType.newInstance();
|
value = returnType.getDeclaredConstructor().newInstance();
|
||||||
emptyInstances.put(returnType, value);
|
emptyInstances.put(returnType, value);
|
||||||
}
|
}
|
||||||
Class<?> cls = value.getClass();
|
Class<?> cls = value.getClass();
|
||||||
|
|
@ -1190,6 +1203,9 @@ public final class ReflectUtils {
|
||||||
if (actualArgType instanceof ParameterizedType) {
|
if (actualArgType instanceof ParameterizedType) {
|
||||||
returnType = (Class<?>) ((ParameterizedType) actualArgType).getRawType();
|
returnType = (Class<?>) ((ParameterizedType) actualArgType).getRawType();
|
||||||
genericReturnType = actualArgType;
|
genericReturnType = actualArgType;
|
||||||
|
} else if (actualArgType instanceof TypeVariable) {
|
||||||
|
returnType = (Class<?>) ((TypeVariable<?>) actualArgType).getBounds()[0];
|
||||||
|
genericReturnType = actualArgType;
|
||||||
} else {
|
} else {
|
||||||
returnType = (Class<?>) actualArgType;
|
returnType = (Class<?>) actualArgType;
|
||||||
genericReturnType = returnType;
|
genericReturnType = returnType;
|
||||||
|
|
@ -1217,16 +1233,14 @@ public final class ReflectUtils {
|
||||||
|
|
||||||
Set<ParameterizedType> parameterizedTypes = genericTypes.stream()
|
Set<ParameterizedType> parameterizedTypes = genericTypes.stream()
|
||||||
.filter(type -> type instanceof ParameterizedType)// filter ParameterizedType
|
.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());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
if (parameterizedTypes.isEmpty()) { // If not found, try to search super types recursively
|
if (parameterizedTypes.isEmpty()) { // If not found, try to search super types recursively
|
||||||
genericTypes.stream()
|
genericTypes.stream()
|
||||||
.filter(type -> type instanceof Class)
|
.filter(type -> type instanceof Class)
|
||||||
.map(type -> Class.class.cast(type))
|
.map(Class.class::cast)
|
||||||
.forEach(superClass -> {
|
.forEach(superClass -> parameterizedTypes.addAll(findParameterizedTypes(superClass)));
|
||||||
parameterizedTypes.addAll(findParameterizedTypes(superClass));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return unmodifiableSet(parameterizedTypes); // build as a Set
|
return unmodifiableSet(parameterizedTypes); // build as a Set
|
||||||
|
|
@ -1316,4 +1330,21 @@ public final class ReflectUtils {
|
||||||
|
|
||||||
return types;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.utils;
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
import org.apache.dubbo.config.annotation.Service;
|
import org.apache.dubbo.config.annotation.Service;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
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.AnnotationUtils.getAttribute;
|
||||||
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
|
import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
|
||||||
import static org.apache.dubbo.common.utils.ClassUtils.isGenericClass;
|
import static org.apache.dubbo.common.utils.ClassUtils.isGenericClass;
|
||||||
|
|
@ -36,6 +40,13 @@ import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
|
||||||
*/
|
*/
|
||||||
public class ServiceAnnotationResolver {
|
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 Annotation serviceAnnotation;
|
||||||
|
|
||||||
private final Class<?> serviceType;
|
private final Class<?> serviceType;
|
||||||
|
|
@ -47,16 +58,18 @@ public class ServiceAnnotationResolver {
|
||||||
|
|
||||||
private Annotation getServiceAnnotation(Class<?> serviceType) {
|
private Annotation getServiceAnnotation(Class<?> serviceType) {
|
||||||
|
|
||||||
Annotation serviceAnnotation = serviceType.getAnnotation(Service.class);
|
Annotation serviceAnnotation = null;
|
||||||
|
|
||||||
if (serviceAnnotation == null) {
|
for (Class<? extends Annotation> serviceAnnotationClass : SERVICE_ANNOTATION_CLASSES) {
|
||||||
serviceAnnotation = serviceType.getAnnotation(com.alibaba.dubbo.config.annotation.Service.class);
|
serviceAnnotation = serviceType.getAnnotation(serviceAnnotationClass);
|
||||||
|
if (serviceAnnotation != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serviceAnnotation == null) {
|
if (serviceAnnotation == null) {
|
||||||
throw new IllegalArgumentException(format("@%s or @%s can't be found in the service type[%s].",
|
throw new IllegalArgumentException(format("Any annotation of [%s] can't be annotated in the service type[%s].",
|
||||||
Service.class.getName(),
|
SERVICE_ANNOTATION_CLASSES,
|
||||||
com.alibaba.dubbo.config.annotation.Service.class.getName(),
|
|
||||||
serviceType.getName()
|
serviceType.getName()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,11 +200,7 @@ public class UrlUtils {
|
||||||
if (version != null && version.length() > 0) {
|
if (version != null && version.length() > 0) {
|
||||||
name = name + ":" + version;
|
name = name + ":" + version;
|
||||||
}
|
}
|
||||||
Map<String, String> newUrls = newRegister.get(name);
|
Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>());
|
||||||
if (newUrls == null) {
|
|
||||||
newUrls = new HashMap<String, String>();
|
|
||||||
newRegister.put(name, newUrls);
|
|
||||||
}
|
|
||||||
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
|
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -261,11 +257,7 @@ public class UrlUtils {
|
||||||
params.put("version", name.substring(i + 1));
|
params.put("version", name.substring(i + 1));
|
||||||
name = name.substring(0, i);
|
name = name.substring(0, i);
|
||||||
}
|
}
|
||||||
Map<String, String> newUrls = newRegister.get(name);
|
Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<String, String>());
|
||||||
if (newUrls == null) {
|
|
||||||
newUrls = new HashMap<String, String>();
|
|
||||||
newRegister.put(name, newUrls);
|
|
||||||
}
|
|
||||||
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
|
newUrls.put(serviceUrl, StringUtils.toQueryString(params));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -324,11 +316,7 @@ public class UrlUtils {
|
||||||
if (version != null && version.length() > 0) {
|
if (version != null && version.length() > 0) {
|
||||||
name = name + ":" + version;
|
name = name + ":" + version;
|
||||||
}
|
}
|
||||||
Map<String, String> newUrls = newNotify.get(name);
|
Map<String, String> newUrls = newNotify.computeIfAbsent(name, k -> new HashMap<String, String>());
|
||||||
if (newUrls == null) {
|
|
||||||
newUrls = new HashMap<String, String>();
|
|
||||||
newNotify.put(name, newUrls);
|
|
||||||
}
|
|
||||||
newUrls.put(url, StringUtils.toQueryString(params));
|
newUrls.put(url, StringUtils.toQueryString(params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.model.AsyncMethodInfo;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -86,6 +87,11 @@ public abstract class AbstractConfig implements Serializable {
|
||||||
|
|
||||||
protected final AtomicBoolean refreshed = new AtomicBoolean(false);
|
protected final AtomicBoolean refreshed = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is default or not
|
||||||
|
*/
|
||||||
|
protected Boolean isDefault;
|
||||||
|
|
||||||
private static String convertLegacyValue(String key, String value) {
|
private static String convertLegacyValue(String key, String value) {
|
||||||
if (value != null && value.length() > 0) {
|
if (value != null && value.length() > 0) {
|
||||||
if ("dubbo.service.max.retry.providers".equals(key)) {
|
if ("dubbo.service.max.retry.providers".equals(key)) {
|
||||||
|
|
@ -373,6 +379,7 @@ public abstract class AbstractConfig implements Serializable {
|
||||||
Method[] methods = annotationClass.getMethods();
|
Method[] methods = annotationClass.getMethods();
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
if (method.getDeclaringClass() != Object.class
|
if (method.getDeclaringClass() != Object.class
|
||||||
|
&& method.getDeclaringClass()!= Annotation.class
|
||||||
&& method.getReturnType() != void.class
|
&& method.getReturnType() != void.class
|
||||||
&& method.getParameterTypes().length == 0
|
&& method.getParameterTypes().length == 0
|
||||||
&& Modifier.isPublic(method.getModifiers())
|
&& Modifier.isPublic(method.getModifiers())
|
||||||
|
|
@ -536,7 +543,7 @@ public abstract class AbstractConfig implements Serializable {
|
||||||
buf.append(" ");
|
buf.append(" ");
|
||||||
buf.append(key);
|
buf.append(key);
|
||||||
buf.append("=\"");
|
buf.append("=\"");
|
||||||
buf.append(value);
|
buf.append(key.equals("password") ? "******" : value);
|
||||||
buf.append("\"");
|
buf.append("\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -628,4 +635,12 @@ public abstract class AbstractConfig implements Serializable {
|
||||||
|
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isDefault() {
|
||||||
|
return isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefault(Boolean isDefault) {
|
||||||
|
this.isDefault = isDefault;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.config.context.ConfigManager;
|
import org.apache.dubbo.config.context.ConfigManager;
|
||||||
import org.apache.dubbo.config.support.Parameter;
|
import org.apache.dubbo.config.support.Parameter;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
import org.apache.dubbo.rpc.model.ServiceMetadata;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -52,6 +53,21 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
||||||
|
|
||||||
private static final long serialVersionUID = -1559314110797223229L;
|
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
|
* 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) {
|
public void completeCompoundConfigs(AbstractInterfaceConfig interfaceConfig) {
|
||||||
if (interfaceConfig != null) {
|
if (interfaceConfig != null) {
|
||||||
if (application == null) {
|
if (application == null) {
|
||||||
|
|
@ -320,15 +340,16 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
setModule(interfaceConfig.getModule());
|
setModule(interfaceConfig.getModule());
|
||||||
}
|
}
|
||||||
if (registries == null) {
|
if (notHasSelfRegistryProperty()) {
|
||||||
setRegistries(interfaceConfig.getRegistries());
|
setRegistries(interfaceConfig.getRegistries());
|
||||||
|
setRegistryIds(interfaceConfig.getRegistryIds());
|
||||||
}
|
}
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
setMonitor(interfaceConfig.getMonitor());
|
setMonitor(interfaceConfig.getMonitor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (module != null) {
|
if (module != null) {
|
||||||
if (registries == null) {
|
if (notHasSelfRegistryProperty()) {
|
||||||
setRegistries(module.getRegistries());
|
setRegistries(module.getRegistries());
|
||||||
}
|
}
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
|
|
@ -336,8 +357,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (application != null) {
|
if (application != null) {
|
||||||
if (registries == null) {
|
if (notHasSelfRegistryProperty()) {
|
||||||
setRegistries(application.getRegistries());
|
setRegistries(application.getRegistries());
|
||||||
|
setRegistryIds(application.getRegistryIds());
|
||||||
}
|
}
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
setMonitor(application.getMonitor());
|
setMonitor(application.getMonitor());
|
||||||
|
|
@ -346,10 +368,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void computeValidRegistryIds() {
|
protected void computeValidRegistryIds() {
|
||||||
if (StringUtils.isEmpty(getRegistryIds())) {
|
if (application != null && notHasSelfRegistryProperty()) {
|
||||||
if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryIds())) {
|
setRegistries(application.getRegistries());
|
||||||
setRegistryIds(getApplication().getRegistryIds());
|
setRegistryIds(application.getRegistryIds());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -691,4 +712,46 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
||||||
public SslConfig getSslConfig() {
|
public SslConfig getSslConfig() {
|
||||||
return ApplicationModel.getConfigManager().getSsl().orElse(null);
|
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;
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,15 +71,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
|
||||||
//TODO solve merge problem
|
//TODO solve merge problem
|
||||||
protected Boolean stubevent;//= Constants.DEFAULT_STUB_EVENT;
|
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
|
* declares which app or service this interface belongs to
|
||||||
|
|
@ -212,21 +204,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
|
||||||
this.sticky = sticky;
|
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")
|
@Parameter(key = "provided-by")
|
||||||
public String getProvidedBy() {
|
public String getProvidedBy() {
|
||||||
|
|
|
||||||
|
|
@ -112,11 +112,6 @@ public class ApplicationConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private MonitorConfig monitor;
|
private MonitorConfig monitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* Is default or not
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory for saving thread dump
|
* Directory for saving thread dump
|
||||||
*/
|
*/
|
||||||
|
|
@ -320,14 +315,6 @@ public class ApplicationConfig extends AbstractConfig {
|
||||||
LoggerFactory.setLoggerAdapter(logger);
|
LoggerFactory.setLoggerAdapter(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parameter(key = DUMP_DIRECTORY)
|
@Parameter(key = DUMP_DIRECTORY)
|
||||||
public String getDumpDirectory() {
|
public String getDumpDirectory() {
|
||||||
return dumpDirectory;
|
return dumpDirectory;
|
||||||
|
|
|
||||||
|
|
@ -119,4 +119,6 @@ public interface Constants {
|
||||||
String MULTI_SERIALIZATION_KEY = "serialize.multiple";
|
String MULTI_SERIALIZATION_KEY = "serialize.multiple";
|
||||||
|
|
||||||
String[] DOT_COMPATIBLE_KEYS = new String[]{"qos-enable", "qos-port", "qos-accept-foreign-ip"};
|
String[] DOT_COMPATIBLE_KEYS = new String[]{"qos-enable", "qos-port", "qos-accept-foreign-ip"};
|
||||||
|
|
||||||
|
String IGNORE_CHECK_KEYS = "ignoreCheckKeys";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
|
||||||
|
|
||||||
private static final long serialVersionUID = 2827274711143680600L;
|
private static final long serialVersionUID = 2827274711143680600L;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to use the default protocol
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Networking framework client uses: netty, mina, etc.
|
* 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));
|
System.setProperty("sun.rmi.transport.tcp.responseTimeout", String.valueOf(timeout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClient() {
|
public String getClient() {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
@ -93,14 +84,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
|
||||||
this.threadpool = threadpool;
|
this.threadpool = threadpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCorethreads() {
|
public Integer getCorethreads() {
|
||||||
return corethreads;
|
return corethreads;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@ public class MetadataReportConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private String registry;
|
private String registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File for saving metadata center dynamic list
|
||||||
|
*/
|
||||||
|
private String file;
|
||||||
|
|
||||||
|
|
||||||
public MetadataReportConfig() {
|
public MetadataReportConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,4 +231,12 @@ public class MetadataReportConfig extends AbstractConfig {
|
||||||
public void setRegistry(String registry) {
|
public void setRegistry(String registry) {
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,15 +139,28 @@ public class MethodConfig extends AbstractMethodConfig {
|
||||||
|
|
||||||
this.setReturn(method.isReturn());
|
this.setReturn(method.isReturn());
|
||||||
|
|
||||||
//TODO callback method processing is not completed
|
String split = ".";
|
||||||
if(!"".equals(method.oninvoke())){
|
|
||||||
this.setOninvoke(method.oninvoke());
|
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())){
|
if (!"".equals(method.onreturn()) && method.onreturn().lastIndexOf(split) > 0) {
|
||||||
this.setOnreturn(method.onreturn());
|
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())){
|
if (!"".equals(method.onthrow()) && method.onthrow().lastIndexOf(split) > 0) {
|
||||||
this.setOnthrow(method.onthrow());
|
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) {
|
if (method.arguments() != null && method.arguments().length != 0) {
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,6 @@ public class ModuleConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private MonitorConfig monitor;
|
private MonitorConfig monitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* If it's default
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
public ModuleConfig() {
|
public ModuleConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,12 +137,4 @@ public class ModuleConfig extends AbstractConfig {
|
||||||
this.monitor = new MonitorConfig(monitor);
|
this.monitor = new MonitorConfig(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,6 @@ public class MonitorConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> parameters;
|
private Map<String, String> parameters;
|
||||||
|
|
||||||
/**
|
|
||||||
* If it's default
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
public MonitorConfig() {
|
public MonitorConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,14 +130,6 @@ public class MonitorConfig extends AbstractConfig {
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInterval() {
|
public String getInterval() {
|
||||||
return interval;
|
return interval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,11 @@ public class ProtocolConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private Integer iothreads;
|
private Integer iothreads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
|
||||||
|
*/
|
||||||
|
private Integer alive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread pool's queue length
|
* Thread pool's queue length
|
||||||
*/
|
*/
|
||||||
|
|
@ -193,11 +198,6 @@ public class ProtocolConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> parameters;
|
private Map<String, String> parameters;
|
||||||
|
|
||||||
/**
|
|
||||||
* If it's default
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
private Boolean sslEnabled;
|
private Boolean sslEnabled;
|
||||||
|
|
||||||
public ProtocolConfig() {
|
public ProtocolConfig() {
|
||||||
|
|
@ -300,6 +300,14 @@ public class ProtocolConfig extends AbstractConfig {
|
||||||
this.iothreads = iothreads;
|
this.iothreads = iothreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getAlive() {
|
||||||
|
return alive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlive(Integer alive) {
|
||||||
|
this.alive = alive;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getQueues() {
|
public Integer getQueues() {
|
||||||
return queues;
|
return queues;
|
||||||
}
|
}
|
||||||
|
|
@ -482,14 +490,6 @@ public class ProtocolConfig extends AbstractConfig {
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDefault() {
|
|
||||||
return isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parameter(key = SSL_ENABLED_KEY)
|
@Parameter(key = SSL_ENABLED_KEY)
|
||||||
public Boolean getSslEnabled() {
|
public Boolean getSslEnabled() {
|
||||||
return sslEnabled;
|
return sslEnabled;
|
||||||
|
|
@ -540,4 +540,46 @@ public class ProtocolConfig extends AbstractConfig {
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return StringUtils.isNotEmpty(name);
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,11 @@ public class ProviderConfig extends AbstractServiceConfig {
|
||||||
*/
|
*/
|
||||||
private Integer iothreads;
|
private Integer iothreads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
|
||||||
|
*/
|
||||||
|
private Integer alive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread pool queue length
|
* Thread pool queue length
|
||||||
*/
|
*/
|
||||||
|
|
@ -149,26 +154,17 @@ public class ProviderConfig extends AbstractServiceConfig {
|
||||||
*/
|
*/
|
||||||
private Integer wait;
|
private Integer wait;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to use the default protocol
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setProtocol(String protocol) {
|
public void setProtocol(String protocol) {
|
||||||
this.protocols = new ArrayList<>(Arrays.asList(new ProtocolConfig(protocol)));
|
this.protocols = new ArrayList<>(Arrays.asList(new ProtocolConfig(protocol)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@Parameter(excluded = true)
|
@Parameter(excluded = true)
|
||||||
public Boolean isDefault() {
|
public Boolean isDefault() {
|
||||||
return isDefault;
|
return isDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void setDefault(Boolean isDefault) {
|
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parameter(excluded = true)
|
@Parameter(excluded = true)
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return host;
|
return host;
|
||||||
|
|
@ -240,6 +236,14 @@ public class ProviderConfig extends AbstractServiceConfig {
|
||||||
this.iothreads = iothreads;
|
this.iothreads = iothreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getAlive() {
|
||||||
|
return alive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlive(Integer alive) {
|
||||||
|
this.alive = alive;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getQueues() {
|
public Integer getQueues() {
|
||||||
return queues;
|
return queues;
|
||||||
}
|
}
|
||||||
|
|
@ -425,4 +429,35 @@ public class ProviderConfig extends AbstractServiceConfig {
|
||||||
this.wait = wait;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
|
||||||
|
|
||||||
private static final long serialVersionUID = -5864351140409987595L;
|
private static final long serialVersionUID = -5864351140409987595L;
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface name of the reference service
|
|
||||||
*/
|
|
||||||
protected String interfaceName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface class of the reference service
|
* The interface class of the reference service
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,7 +67,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
|
||||||
*/
|
*/
|
||||||
protected String protocol;
|
protected String protocol;
|
||||||
|
|
||||||
protected ServiceMetadata serviceMetadata;
|
|
||||||
|
|
||||||
public ReferenceConfigBase() {
|
public ReferenceConfigBase() {
|
||||||
serviceMetadata = new ServiceMetadata();
|
serviceMetadata = new ServiceMetadata();
|
||||||
|
|
@ -268,12 +262,14 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void computeValidRegistryIds() {
|
protected void computeValidRegistryIds() {
|
||||||
super.computeValidRegistryIds();
|
if (consumer != null) {
|
||||||
if (StringUtils.isEmpty(getRegistryIds())) {
|
if (notHasSelfRegistryProperty()) {
|
||||||
if (getConsumer() != null && StringUtils.isNotEmpty(getConsumer().getRegistryIds())) {
|
setRegistries(consumer.getRegistries());
|
||||||
setRegistryIds(getConsumer().getRegistryIds());
|
setRegistryIds(consumer.getRegistryIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.computeValidRegistryIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parameter(excluded = true)
|
@Parameter(excluded = true)
|
||||||
|
|
|
||||||
|
|
@ -139,11 +139,6 @@ public class RegistryConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> parameters;
|
private Map<String, String> parameters;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether it's default
|
|
||||||
*/
|
|
||||||
private Boolean isDefault;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple the registry. both useful for provider and consumer
|
* 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() {
|
public Boolean getSimplified() {
|
||||||
return simplified;
|
return simplified;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
|
||||||
|
|
||||||
private static final long serialVersionUID = 3033787999037024738L;
|
private static final long serialVersionUID = 3033787999037024738L;
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface name of the exported service
|
|
||||||
*/
|
|
||||||
protected String interfaceName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface class of the exported service
|
* The interface class of the exported service
|
||||||
|
|
@ -78,7 +75,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
|
||||||
*/
|
*/
|
||||||
protected volatile String generic;
|
protected volatile String generic;
|
||||||
|
|
||||||
protected ServiceMetadata serviceMetadata;
|
|
||||||
|
|
||||||
public ServiceConfigBase() {
|
public ServiceConfigBase() {
|
||||||
serviceMetadata = new ServiceMetadata();
|
serviceMetadata = new ServiceMetadata();
|
||||||
|
|
@ -202,32 +199,35 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkProtocol() {
|
public void checkProtocol() {
|
||||||
|
if (provider != null && notHasSelfProtocolProperty()) {
|
||||||
|
setProtocols(provider.getProtocols());
|
||||||
|
setProtocolIds(provider.getProtocolIds());
|
||||||
|
}
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(protocols) && provider != null) {
|
if (CollectionUtils.isEmpty(protocols) && provider != null) {
|
||||||
setProtocols(provider.getProtocols());
|
setProtocols(provider.getProtocols());
|
||||||
}
|
}
|
||||||
convertProtocolIdsToProtocols();
|
convertProtocolIdsToProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean notHasSelfProtocolProperty() {
|
||||||
|
return CollectionUtils.isEmpty(protocols) && StringUtils.isEmpty(protocolIds);
|
||||||
|
}
|
||||||
|
|
||||||
public void completeCompoundConfigs() {
|
public void completeCompoundConfigs() {
|
||||||
super.completeCompoundConfigs(provider);
|
super.completeCompoundConfigs(provider);
|
||||||
if (provider != null) {
|
if (provider != null) {
|
||||||
if (protocols == null) {
|
if (notHasSelfProtocolProperty()) {
|
||||||
setProtocols(provider.getProtocols());
|
setProtocols(provider.getProtocols());
|
||||||
|
setProtocolIds(provider.getProtocolIds());
|
||||||
}
|
}
|
||||||
if (configCenter == null) {
|
if (configCenter == null) {
|
||||||
setConfigCenter(provider.getConfigCenter());
|
setConfigCenter(provider.getConfigCenter());
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(registryIds)) {
|
|
||||||
setRegistryIds(provider.getRegistryIds());
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(protocolIds)) {
|
|
||||||
setProtocolIds(provider.getProtocolIds());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convertProtocolIdsToProtocols() {
|
private void convertProtocolIdsToProtocols() {
|
||||||
computeValidProtocolIds();
|
|
||||||
if (StringUtils.isEmpty(protocolIds)) {
|
if (StringUtils.isEmpty(protocolIds)) {
|
||||||
if (CollectionUtils.isEmpty(protocols)) {
|
if (CollectionUtils.isEmpty(protocols)) {
|
||||||
List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
|
List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
|
||||||
|
|
@ -292,9 +292,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
|
||||||
setInterface(interfaceClass);
|
setInterface(interfaceClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInterface() {
|
|
||||||
return interfaceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterface(Class<?> interfaceClass) {
|
public void setInterface(Class<?> interfaceClass) {
|
||||||
if (interfaceClass != null && !interfaceClass.isInterface()) {
|
if (interfaceClass != null && !interfaceClass.isInterface()) {
|
||||||
|
|
@ -304,14 +302,6 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
|
||||||
setInterface(interfaceClass == null ? null : interfaceClass.getName());
|
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() {
|
public T getRef() {
|
||||||
return ref;
|
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;
|
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
|
@Override
|
||||||
protected void computeValidRegistryIds() {
|
protected void computeValidRegistryIds() {
|
||||||
super.computeValidRegistryIds();
|
if (provider != null && notHasSelfRegistryProperty()) {
|
||||||
if (StringUtils.isEmpty(getRegistryIds())) {
|
setRegistries(provider.getRegistries());
|
||||||
if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getRegistryIds())) {
|
setRegistryIds(provider.getRegistryIds());
|
||||||
setRegistryIds(getProvider().getRegistryIds());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.computeValidRegistryIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void export();
|
public abstract void export();
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ package org.apache.dubbo.config;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
import org.apache.dubbo.common.utils.IOUtils;
|
||||||
import org.apache.dubbo.config.support.Parameter;
|
import org.apache.dubbo.config.support.Parameter;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.IOException;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
@ -120,9 +120,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.clientTrustCertCollectionPath = clientTrustCertCollectionPath;
|
this.clientTrustCertCollectionPath = clientTrustCertCollectionPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getServerKeyCertChainPathStream() throws FileNotFoundException {
|
public InputStream getServerKeyCertChainPathStream() throws IOException {
|
||||||
if (serverKeyCertChainPath != null) {
|
if (serverKeyCertChainPath != null) {
|
||||||
serverKeyCertChainPathStream = new FileInputStream(serverKeyCertChainPath);
|
serverKeyCertChainPathStream = IOUtils.getURL(serverKeyCertChainPath).openStream();
|
||||||
}
|
}
|
||||||
return serverKeyCertChainPathStream;
|
return serverKeyCertChainPathStream;
|
||||||
}
|
}
|
||||||
|
|
@ -131,9 +131,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.serverKeyCertChainPathStream = serverKeyCertChainPathStream;
|
this.serverKeyCertChainPathStream = serverKeyCertChainPathStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getServerPrivateKeyPathStream() throws FileNotFoundException {
|
public InputStream getServerPrivateKeyPathStream() throws IOException {
|
||||||
if (serverPrivateKeyPath != null) {
|
if (serverPrivateKeyPath != null) {
|
||||||
serverPrivateKeyPathStream = new FileInputStream(serverPrivateKeyPath);
|
serverPrivateKeyPathStream = IOUtils.getURL(serverPrivateKeyPath).openStream();
|
||||||
}
|
}
|
||||||
return serverPrivateKeyPathStream;
|
return serverPrivateKeyPathStream;
|
||||||
}
|
}
|
||||||
|
|
@ -142,9 +142,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.serverPrivateKeyPathStream = serverPrivateKeyPathStream;
|
this.serverPrivateKeyPathStream = serverPrivateKeyPathStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getServerTrustCertCollectionPathStream() throws FileNotFoundException {
|
public InputStream getServerTrustCertCollectionPathStream() throws IOException {
|
||||||
if (serverTrustCertCollectionPath != null) {
|
if (serverTrustCertCollectionPath != null) {
|
||||||
serverTrustCertCollectionPathStream = new FileInputStream(serverTrustCertCollectionPath);
|
serverTrustCertCollectionPathStream = IOUtils.getURL(serverTrustCertCollectionPath).openStream();
|
||||||
}
|
}
|
||||||
return serverTrustCertCollectionPathStream;
|
return serverTrustCertCollectionPathStream;
|
||||||
}
|
}
|
||||||
|
|
@ -153,9 +153,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.serverTrustCertCollectionPathStream = serverTrustCertCollectionPathStream;
|
this.serverTrustCertCollectionPathStream = serverTrustCertCollectionPathStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getClientKeyCertChainPathStream() throws FileNotFoundException {
|
public InputStream getClientKeyCertChainPathStream() throws IOException {
|
||||||
if (clientKeyCertChainPath != null) {
|
if (clientKeyCertChainPath != null) {
|
||||||
clientKeyCertChainPathStream = new FileInputStream(clientKeyCertChainPath);
|
clientKeyCertChainPathStream = IOUtils.getURL(clientKeyCertChainPath).openStream();
|
||||||
}
|
}
|
||||||
return clientKeyCertChainPathStream;
|
return clientKeyCertChainPathStream;
|
||||||
}
|
}
|
||||||
|
|
@ -164,9 +164,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.clientKeyCertChainPathStream = clientKeyCertChainPathStream;
|
this.clientKeyCertChainPathStream = clientKeyCertChainPathStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getClientPrivateKeyPathStream() throws FileNotFoundException {
|
public InputStream getClientPrivateKeyPathStream() throws IOException {
|
||||||
if (clientPrivateKeyPath != null) {
|
if (clientPrivateKeyPath != null) {
|
||||||
clientPrivateKeyPathStream = new FileInputStream(clientPrivateKeyPath);
|
clientPrivateKeyPathStream = IOUtils.getURL(clientPrivateKeyPath).openStream();
|
||||||
}
|
}
|
||||||
return clientPrivateKeyPathStream;
|
return clientPrivateKeyPathStream;
|
||||||
}
|
}
|
||||||
|
|
@ -175,9 +175,9 @@ public class SslConfig extends AbstractConfig {
|
||||||
this.clientPrivateKeyPathStream = clientPrivateKeyPathStream;
|
this.clientPrivateKeyPathStream = clientPrivateKeyPathStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getClientTrustCertCollectionPathStream() throws FileNotFoundException {
|
public InputStream getClientTrustCertCollectionPathStream() throws IOException {
|
||||||
if (clientTrustCertCollectionPath != null) {
|
if (clientTrustCertCollectionPath != null) {
|
||||||
clientTrustCertCollectionPathStream = new FileInputStream(clientTrustCertCollectionPath);
|
clientTrustCertCollectionPathStream = IOUtils.getURL(clientTrustCertCollectionPath).openStream();
|
||||||
}
|
}
|
||||||
return clientTrustCertCollectionPathStream;
|
return clientTrustCertCollectionPathStream;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.config.annotation;
|
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.common.constants.RegistryConstants;
|
||||||
import org.apache.dubbo.config.ReferenceConfigBase;
|
import org.apache.dubbo.config.ReferenceConfigBase;
|
||||||
|
|
||||||
|
|
@ -163,8 +165,9 @@ public @interface DubboReference {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
|
* 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
|
* 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
|
* Load balance strategy, legal values include: random, roundrobin, leastactive
|
||||||
* <p>
|
* you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM} ……
|
||||||
* see Constants#DEFAULT_LOADBALANCE
|
|
||||||
*/
|
*/
|
||||||
String loadbalance() default "";
|
String loadbalance() default LoadbalanceRules.EMPTY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to enable async invocation, default value is false
|
* Whether to enable async invocation, default value is false
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
package org.apache.dubbo.config.annotation;
|
package org.apache.dubbo.config.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.constants.ClusterRules;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Inherited;
|
import java.lang.annotation.Inherited;
|
||||||
|
|
@ -123,8 +125,9 @@ public @interface DubboService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
|
* 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
|
* 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
|
* 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
|
* Whether to enable async invocation, default value is false
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public class ConfigConfigurationAdapter implements Configuration {
|
||||||
|
|
||||||
public ConfigConfigurationAdapter(AbstractConfig config) {
|
public ConfigConfigurationAdapter(AbstractConfig config) {
|
||||||
Map<String, String> configMetadata = config.getMetaData();
|
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()) {
|
for (Map.Entry<String, String> entry : configMetadata.entrySet()) {
|
||||||
String prefix = config.getPrefix().endsWith(".") ? config.getPrefix() : config.getPrefix() + ".";
|
String prefix = config.getPrefix().endsWith(".") ? config.getPrefix() : config.getPrefix() + ".";
|
||||||
String id = StringUtils.isEmpty(config.getId()) ? "" : config.getId() + ".";
|
String id = StringUtils.isEmpty(config.getId()) ? "" : config.getId() + ".";
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
@ -386,9 +387,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
write(() -> {
|
write(this.configsCache::clear);
|
||||||
this.configsCache.clear();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -442,6 +441,18 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
|
||||||
// throw new IllegalStateException("No such " + configType.getName() + " is found");
|
// throw new IllegalStateException("No such " + configType.getName() + " is found");
|
||||||
return null;
|
return null;
|
||||||
} else if (size > 1) {
|
} 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) {
|
if (configWarnLogEnabled && warnLogStatus.get(configType) == null) {
|
||||||
logger.warn("Expected single matching of " + configType + ", but found " + size + " instances, will randomly pick the first one.");
|
logger.warn("Expected single matching of " + configType + ", but found " + size + " instances, will randomly pick the first one.");
|
||||||
warnLogStatus.put(configType, true);
|
warnLogStatus.put(configType, true);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.apache.dubbo.event;
|
||||||
* @since 2.7.5
|
* @since 2.7.5
|
||||||
*/
|
*/
|
||||||
public final class DirectEventDispatcher extends AbstractEventDispatcher {
|
public final class DirectEventDispatcher extends AbstractEventDispatcher {
|
||||||
|
public static final String NAME = "direct";
|
||||||
|
|
||||||
public DirectEventDispatcher() {
|
public DirectEventDispatcher() {
|
||||||
super(DIRECT_EXECUTOR);
|
super(DIRECT_EXECUTOR);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import java.util.concurrent.Executor;
|
||||||
* @see DirectEventDispatcher
|
* @see DirectEventDispatcher
|
||||||
* @since 2.7.5
|
* @since 2.7.5
|
||||||
*/
|
*/
|
||||||
@SPI("direct")
|
@SPI(DirectEventDispatcher.NAME)
|
||||||
public interface EventDispatcher extends Listenable<EventListener<?>> {
|
public interface EventDispatcher extends Listenable<EventListener<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import java.util.concurrent.ForkJoinPool;
|
||||||
* @since 2.7.5
|
* @since 2.7.5
|
||||||
*/
|
*/
|
||||||
public class ParallelEventDispatcher extends AbstractEventDispatcher {
|
public class ParallelEventDispatcher extends AbstractEventDispatcher {
|
||||||
|
public static final String NAME = "parallel";
|
||||||
|
|
||||||
public ParallelEventDispatcher() {
|
public ParallelEventDispatcher() {
|
||||||
super(ForkJoinPool.commonPool());
|
super(ForkJoinPool.commonPool());
|
||||||
|
|
|
||||||
|
|
@ -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_RAW_RETURN;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_BEAN;
|
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_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_NATIVE_JAVA;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_PROTOBUF;
|
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_NATIVE_JAVA.equalsIgnoreCase(generic) /* Streaming generalization call supporting jdk serialization */
|
||||||
|| GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
|
|| GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
|
||||||
|| GENERIC_SERIALIZATION_PROTOBUF.equalsIgnoreCase(generic)
|
|| GENERIC_SERIALIZATION_PROTOBUF.equalsIgnoreCase(generic)
|
||||||
|
|| GENERIC_SERIALIZATION_GSON.equalsIgnoreCase(generic)
|
||||||
|| GENERIC_RAW_RETURN.equalsIgnoreCase(generic));
|
|| GENERIC_RAW_RETURN.equalsIgnoreCase(generic));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -75,6 +77,11 @@ public class ProtocolUtils {
|
||||||
&& GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic);
|
&& 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) {
|
public static boolean isBeanGenericSerialization(String generic) {
|
||||||
return isGeneric(generic) && GENERIC_SERIALIZATION_BEAN.equals(generic);
|
return isGeneric(generic) && GENERIC_SERIALIZATION_BEAN.equals(generic);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common;
|
package org.apache.dubbo.common;
|
||||||
|
|
||||||
|
import net.bytebuddy.utility.RandomString;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
|
@ -25,16 +30,53 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
* Created by LinShunkang on 2020/03/12
|
* Created by LinShunkang on 2020/03/12
|
||||||
*/
|
*/
|
||||||
public class URLStrParserTest {
|
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×tamp=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
|
@Test
|
||||||
public void test() {
|
public void testEncoded() {
|
||||||
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";
|
testCases.forEach(testCase -> {
|
||||||
System.out.println(URLStrParser.parseEncodedStr(str));
|
assertThat(URLStrParser.parseEncodedStr(URL.encode(testCase)), equalTo(URL.valueOf(testCase)));
|
||||||
|
});
|
||||||
|
|
||||||
String decodeStr = URL.decode(str);
|
errorEncodedCases.forEach(errorCase -> {
|
||||||
URL originalUrl = URL.valueOf(decodeStr);
|
Assertions.assertThrows(RuntimeException.class,
|
||||||
assertThat(URLStrParser.parseEncodedStr(str), equalTo(originalUrl));
|
() -> URLStrParser.parseEncodedStr(errorCase));
|
||||||
assertThat(URLStrParser.parseDecodedStr(decodeStr), equalTo(originalUrl));
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
Loading…
Reference in New Issue