Compare commits
281 Commits
3.2
...
3.3.0-beta
| Author | SHA1 | Date |
|---|---|---|
|
|
fc45dd887c | |
|
|
3c4247eb58 | |
|
|
92e7b5d807 | |
|
|
ab6ce115f5 | |
|
|
867f79e030 | |
|
|
5985116582 | |
|
|
2486674828 | |
|
|
35adffac48 | |
|
|
667f98a459 | |
|
|
e49b8b2411 | |
|
|
e4fa369b29 | |
|
|
5d5d0365b5 | |
|
|
88e6772ba0 | |
|
|
64264f6c46 | |
|
|
b831c26e83 | |
|
|
48df310ce7 | |
|
|
1d1671ef80 | |
|
|
bc83ae32c9 | |
|
|
3cc6338a80 | |
|
|
e201865274 | |
|
|
1e8b699fb9 | |
|
|
5dceb96c6b | |
|
|
bb06ff3fe7 | |
|
|
3867c4dcb4 | |
|
|
721ae9493d | |
|
|
e29fac8c18 | |
|
|
6a318d2553 | |
|
|
f2b7a044c6 | |
|
|
48ad8143bc | |
|
|
32f4cb53df | |
|
|
6f1a41f125 | |
|
|
935849f4ce | |
|
|
b5bb04496c | |
|
|
1f6d441de6 | |
|
|
8368262406 | |
|
|
225ca9d232 | |
|
|
80ffcd7a85 | |
|
|
b95695bf4f | |
|
|
e8ccb01886 | |
|
|
e826b0c20d | |
|
|
2c38cab1d2 | |
|
|
31f4b3dca3 | |
|
|
fa71998d59 | |
|
|
117db47505 | |
|
|
191697a340 | |
|
|
fa16bed3a3 | |
|
|
6a44987f5f | |
|
|
b9e1dc057f | |
|
|
d1c6e558a7 | |
|
|
487fa4f7c7 | |
|
|
1686383ced | |
|
|
7fee7dd99d | |
|
|
07440a0679 | |
|
|
583b57be2b | |
|
|
10af737925 | |
|
|
7cf5fe42f2 | |
|
|
314547ef4d | |
|
|
53553dcef4 | |
|
|
0840c60e54 | |
|
|
a12975aa93 | |
|
|
0788f7490e | |
|
|
0c7e32ff15 | |
|
|
55b6d170d9 | |
|
|
b338e20190 | |
|
|
944be946ac | |
|
|
0cce4c8afe | |
|
|
4a7f00f731 | |
|
|
d5c484a643 | |
|
|
ca6ceaa5a4 | |
|
|
0f8be9ec93 | |
|
|
9c1175bc28 | |
|
|
9b3a32f8d6 | |
|
|
1145b4015b | |
|
|
cf53c38179 | |
|
|
da2dd6d2a1 | |
|
|
cb92fcc19e | |
|
|
b14e5e3a12 | |
|
|
9b3073c2f4 | |
|
|
76390eed4e | |
|
|
3f2e0e18c9 | |
|
|
22b3c29b08 | |
|
|
1dd289d405 | |
|
|
0fa88a1180 | |
|
|
044a775373 | |
|
|
97d5563990 | |
|
|
70b1ecb662 | |
|
|
e2ea0046d2 | |
|
|
d5b7941c63 | |
|
|
a1bfa7b8f7 | |
|
|
ce570dd932 | |
|
|
2dde7ac09e | |
|
|
e60f24cb7f | |
|
|
9211a91d1c | |
|
|
c38fa0ac8b | |
|
|
46af145730 | |
|
|
bfd748ee5d | |
|
|
74dd87c15b | |
|
|
d018475f73 | |
|
|
2a0755c279 | |
|
|
cb5ff2aace | |
|
|
36e0ee0a96 | |
|
|
3de3ccf457 | |
|
|
5b0b86b11d | |
|
|
6118aa55f2 | |
|
|
2f4a78ee38 | |
|
|
0fccd2ccae | |
|
|
ad803e1c84 | |
|
|
8f7446c81d | |
|
|
c8f7269e41 | |
|
|
0c766ad462 | |
|
|
4737eafcb4 | |
|
|
5cf765889e | |
|
|
c302fcccd8 | |
|
|
40201078b0 | |
|
|
74978ca003 | |
|
|
40f44f91f5 | |
|
|
93ec8e368d | |
|
|
af0f45f7cd | |
|
|
3f48269562 | |
|
|
7e0954b8cf | |
|
|
a53228d545 | |
|
|
650ee3b9d4 | |
|
|
f441e79d8d | |
|
|
633bdbd08f | |
|
|
7a44bb8ba1 | |
|
|
04594755a2 | |
|
|
fe4a9f3592 | |
|
|
3aacb6642c | |
|
|
976516cbc1 | |
|
|
39611ea28c | |
|
|
31712083f4 | |
|
|
c877d6e6f9 | |
|
|
a3096054ed | |
|
|
c3b0c2eefa | |
|
|
865f68bdc5 | |
|
|
2b62e88974 | |
|
|
90bc72e641 | |
|
|
d979b211ce | |
|
|
88deb9be3d | |
|
|
d9743aa86e | |
|
|
c7e548d9a2 | |
|
|
70469346b2 | |
|
|
647f58a02b | |
|
|
e155591adb | |
|
|
35b6682393 | |
|
|
26b9f3e48d | |
|
|
48c82c0462 | |
|
|
35b4c0aba9 | |
|
|
a46188082c | |
|
|
d00757e65b | |
|
|
539bb11ae7 | |
|
|
a15ab195c6 | |
|
|
f635de7ba2 | |
|
|
cd35ca829a | |
|
|
7188a3a5cb | |
|
|
9681515f18 | |
|
|
ba94cf0b17 | |
|
|
d0c41f512e | |
|
|
c98c4873ff | |
|
|
0562b64828 | |
|
|
7696e1b42c | |
|
|
027aba599e | |
|
|
3e50bdd16f | |
|
|
8bdcaf6865 | |
|
|
c72c55aa67 | |
|
|
bbee466e44 | |
|
|
acee3e2f03 | |
|
|
a709b2803c | |
|
|
1848e400a0 | |
|
|
0dab17f11d | |
|
|
2bf662ce90 | |
|
|
d050b9c6ec | |
|
|
0c9d5e2f73 | |
|
|
bcd5caf7df | |
|
|
0b2b9f735a | |
|
|
a0e7ebc735 | |
|
|
7246fad6b5 | |
|
|
c96a8f3719 | |
|
|
660d5a2ecd | |
|
|
4f32e0aba3 | |
|
|
fb0911de97 | |
|
|
0fd51b1ca0 | |
|
|
54da4da033 | |
|
|
cff9bfd1d2 | |
|
|
9eb49e24c3 | |
|
|
0f61286a78 | |
|
|
abb2d3834d | |
|
|
4b5c186076 | |
|
|
3ed2dacbef | |
|
|
99ba6e3037 | |
|
|
8009c72030 | |
|
|
dad3b070cd | |
|
|
fd04ef711b | |
|
|
d596eeb151 | |
|
|
fe2af7e354 | |
|
|
cfd0be3a3a | |
|
|
7e6a32ba68 | |
|
|
059b75c533 | |
|
|
36a80e4db7 | |
|
|
bf3d4f4ca3 | |
|
|
8e55dae8f9 | |
|
|
f91246ab09 | |
|
|
186ec674bf | |
|
|
98d6a853a9 | |
|
|
679ce4496c | |
|
|
4e9a0a41fc | |
|
|
7a4ec6c525 | |
|
|
ae150c01e5 | |
|
|
56de12127b | |
|
|
629bee3987 | |
|
|
5ae875d951 | |
|
|
04f3fe7d2b | |
|
|
8bfdf1e38c | |
|
|
059fdf2613 | |
|
|
7c971ca1bd | |
|
|
b18eeb7077 | |
|
|
6c5a876f31 | |
|
|
ce65317207 | |
|
|
046898bbc8 | |
|
|
29d9c070d4 | |
|
|
8fefd95a98 | |
|
|
2973426b2a | |
|
|
70605f4dd0 | |
|
|
d1719c5358 | |
|
|
0e17f4f168 | |
|
|
72e5d20ce9 | |
|
|
0db8605974 | |
|
|
80d496c5b1 | |
|
|
093fb7c208 | |
|
|
f78b4f5dea | |
|
|
1f8a0fa5ec | |
|
|
f2ec217f54 | |
|
|
c7d411c3cb | |
|
|
8bb17b85f2 | |
|
|
4b62513dff | |
|
|
9bbf7625a8 | |
|
|
0d4e8304bc | |
|
|
33a8063309 | |
|
|
d4c2852caf | |
|
|
48cc5b24de | |
|
|
37f150263a | |
|
|
95207b9079 | |
|
|
da8d0cd994 | |
|
|
27e6838c3b | |
|
|
1c65617fb1 | |
|
|
cf2a63580e | |
|
|
d6776e4008 | |
|
|
b14201f393 | |
|
|
c96a06eba1 | |
|
|
1e59ab524a | |
|
|
fd14e7b76f | |
|
|
642f741dba | |
|
|
85bc6ea472 | |
|
|
391d3cdb35 | |
|
|
2031a4c531 | |
|
|
e642e72ce8 | |
|
|
4604b8074a | |
|
|
30daba2d74 | |
|
|
1f39543632 | |
|
|
71046bdd6f | |
|
|
ae4899a462 | |
|
|
7661cab6f5 | |
|
|
d798e7c3be | |
|
|
34eb252178 | |
|
|
59758f4b58 | |
|
|
52e4e4e301 | |
|
|
71cc51bf69 | |
|
|
a80ad7f505 | |
|
|
9f0e1589a5 | |
|
|
471f44b52d | |
|
|
992abd2d34 | |
|
|
9d9df82194 | |
|
|
6c8f79c889 | |
|
|
2997fa6a2e | |
|
|
13558a8e6a | |
|
|
59832d45d4 | |
|
|
fe55491d4a | |
|
|
b23bae38cc | |
|
|
0b6f2e4a8d | |
|
|
414785c05b | |
|
|
52611099ab |
42
.artifacts
42
.artifacts
|
|
@ -19,8 +19,8 @@
|
||||||
dubbo
|
dubbo
|
||||||
dubbo-auth
|
dubbo-auth
|
||||||
dubbo-apache-release
|
dubbo-apache-release
|
||||||
|
dubbo-all-shaded
|
||||||
dubbo-bom
|
dubbo-bom
|
||||||
dubbo-build-tools
|
|
||||||
dubbo-cluster
|
dubbo-cluster
|
||||||
dubbo-common
|
dubbo-common
|
||||||
dubbo-compatible
|
dubbo-compatible
|
||||||
|
|
@ -28,21 +28,18 @@ dubbo-compiler
|
||||||
dubbo-config
|
dubbo-config
|
||||||
dubbo-config-api
|
dubbo-config-api
|
||||||
dubbo-config-spring
|
dubbo-config-spring
|
||||||
|
dubbo-config-spring6
|
||||||
dubbo-configcenter
|
dubbo-configcenter
|
||||||
|
dubbo-configcenter-file
|
||||||
dubbo-configcenter-apollo
|
dubbo-configcenter-apollo
|
||||||
dubbo-configcenter-nacos
|
dubbo-configcenter-nacos
|
||||||
dubbo-configcenter-zookeeper
|
dubbo-configcenter-zookeeper
|
||||||
dubbo-container
|
|
||||||
dubbo-container-api
|
|
||||||
dubbo-container-spring
|
|
||||||
dubbo-core-spi
|
dubbo-core-spi
|
||||||
dubbo-dependencies
|
dubbo-dependencies
|
||||||
dubbo-dependencies-all
|
dubbo-dependencies-all
|
||||||
dubbo-dependencies-bom
|
dubbo-dependencies-bom
|
||||||
dubbo-dependencies-zookeeper
|
|
||||||
dubbo-dependencies-zookeeper-curator5
|
dubbo-dependencies-zookeeper-curator5
|
||||||
dubbo-distribution
|
dubbo-distribution
|
||||||
dubbo-filter
|
|
||||||
dubbo-filter-cache
|
dubbo-filter-cache
|
||||||
dubbo-filter-validation
|
dubbo-filter-validation
|
||||||
dubbo-kubernetes
|
dubbo-kubernetes
|
||||||
|
|
@ -61,11 +58,9 @@ dubbo-metrics-metadata
|
||||||
dubbo-metrics-prometheus
|
dubbo-metrics-prometheus
|
||||||
dubbo-metrics-registry
|
dubbo-metrics-registry
|
||||||
dubbo-metrics-config-center
|
dubbo-metrics-config-center
|
||||||
dubbo-monitor
|
dubbo-metrics-netty
|
||||||
dubbo-monitor-api
|
dubbo-metrics-event
|
||||||
dubbo-monitor-default
|
|
||||||
dubbo-native
|
dubbo-native
|
||||||
dubbo-native-plugin
|
|
||||||
dubbo-parent
|
dubbo-parent
|
||||||
dubbo-plugin
|
dubbo-plugin
|
||||||
dubbo-qos
|
dubbo-qos
|
||||||
|
|
@ -79,16 +74,15 @@ dubbo-registry-nacos
|
||||||
dubbo-registry-zookeeper
|
dubbo-registry-zookeeper
|
||||||
dubbo-remoting
|
dubbo-remoting
|
||||||
dubbo-remoting-api
|
dubbo-remoting-api
|
||||||
dubbo-remoting-http
|
dubbo-remoting-http12
|
||||||
|
dubbo-remoting-http3
|
||||||
dubbo-remoting-netty
|
dubbo-remoting-netty
|
||||||
dubbo-remoting-netty4
|
dubbo-remoting-netty4
|
||||||
dubbo-remoting-zookeeper
|
|
||||||
dubbo-remoting-zookeeper-curator5
|
dubbo-remoting-zookeeper-curator5
|
||||||
dubbo-rpc
|
dubbo-rpc
|
||||||
dubbo-rpc-api
|
dubbo-rpc-api
|
||||||
dubbo-rpc-dubbo
|
dubbo-rpc-dubbo
|
||||||
dubbo-rpc-injvm
|
dubbo-rpc-injvm
|
||||||
dubbo-rpc-rest
|
|
||||||
dubbo-rpc-triple
|
dubbo-rpc-triple
|
||||||
dubbo-security
|
dubbo-security
|
||||||
dubbo-serialization
|
dubbo-serialization
|
||||||
|
|
@ -100,18 +94,28 @@ dubbo-spring-boot
|
||||||
dubbo-spring-boot-actuator
|
dubbo-spring-boot-actuator
|
||||||
dubbo-spring-boot-actuator-compatible
|
dubbo-spring-boot-actuator-compatible
|
||||||
dubbo-spring-boot-autoconfigure
|
dubbo-spring-boot-autoconfigure
|
||||||
|
dubbo-spring-boot-3-autoconfigure
|
||||||
dubbo-spring-boot-autoconfigure-compatible
|
dubbo-spring-boot-autoconfigure-compatible
|
||||||
dubbo-spring-boot-compatible
|
dubbo-spring-boot-compatible
|
||||||
dubbo-spring-boot-observability-starters
|
dubbo-observability-spring-boot-starters
|
||||||
dubbo-spring-boot-observability-autoconfigure
|
dubbo-observability-spring-boot-autoconfigure
|
||||||
dubbo-spring-boot-tracing-brave-zipkin-starter
|
dubbo-tracing-brave-zipkin-spring-boot-starter
|
||||||
dubbo-spring-boot-tracing-otel-zipkin-starter
|
dubbo-tracing-otel-zipkin-spring-boot-starter
|
||||||
dubbo-spring-boot-tracing-otel-otlp-starter
|
dubbo-tracing-otel-otlp-spring-boot-starter
|
||||||
dubbo-spring-boot-observability-starter
|
dubbo-observability-spring-boot-starter
|
||||||
dubbo-spring-boot-starter
|
dubbo-spring-boot-starter
|
||||||
dubbo-spring-boot-starters
|
dubbo-spring-boot-starters
|
||||||
|
dubbo-spring-boot-interceptor
|
||||||
dubbo-nacos-spring-boot-starter
|
dubbo-nacos-spring-boot-starter
|
||||||
dubbo-zookeeper-spring-boot-starter
|
dubbo-zookeeper-spring-boot-starter
|
||||||
dubbo-zookeeper-curator5-spring-boot-starter
|
dubbo-zookeeper-curator5-spring-boot-starter
|
||||||
|
dubbo-sentinel-spring-boot-starter
|
||||||
|
dubbo-seata-spring-boot-starter
|
||||||
dubbo-spring-security
|
dubbo-spring-security
|
||||||
|
dubbo-tracing
|
||||||
dubbo-xds
|
dubbo-xds
|
||||||
|
dubbo-plugin-loom
|
||||||
|
dubbo-rest-jaxrs
|
||||||
|
dubbo-rest-servlet
|
||||||
|
dubbo-rest-spring
|
||||||
|
dubbo-triple-servlet
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,8 @@
|
||||||
## What is the purpose of the change
|
## What is the purpose of the change?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Brief changelog
|
|
||||||
|
|
||||||
|
|
||||||
## Verifying this change
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->
|
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
- [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.
|
||||||
- [ ] Each commit in the pull request should have a meaningful subject line and body.
|
- [x] 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.
|
- [x] Write necessary unit-test to verify your logic correction. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.
|
||||||
- [ ] Check if is necessary to patch to Dubbo 3 if you are work on Dubbo 2.7
|
- [x] Make sure gitHub actions can pass. [Why the workflow is failing and how to fix it?](./CONTRIBUTING.md)
|
||||||
- [ ] 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.
|
|
||||||
- [ ] Add some description to [dubbo-website](https://github.com/apache/dubbo-website) project if you are requesting to add a feature.
|
|
||||||
- [ ] GitHub Actions works fine on your own branch.
|
|
||||||
- [ ] If this contribution is large, please follow the [Software Donation Guide](https://github.com/apache/dubbo/wiki/Software-donation-guide).
|
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ jobs:
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 8
|
java-version: 21
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
name: "Cache local Maven repository"
|
name: "Cache local Maven repository"
|
||||||
with:
|
with:
|
||||||
|
|
@ -199,7 +199,6 @@ jobs:
|
||||||
env:
|
env:
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
DISABLE_FILE_SYSTEM_TEST: true
|
||||||
CURRENT_ROLE: ${{ matrix.case-role }}
|
CURRENT_ROLE: ${{ matrix.case-role }}
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
|
@ -238,7 +237,7 @@ jobs:
|
||||||
openssl rsautl -decrypt -in ${{ github.workspace }}/.tmp/encrypted-sonarcloud-token -out ${{ github.workspace }}/.tmp/decrypted-sonarcloud-token -inkey ${{ github.workspace }}/.tmp/rsa/rsa_private.pem
|
openssl rsautl -decrypt -in ${{ github.workspace }}/.tmp/encrypted-sonarcloud-token -out ${{ github.workspace }}/.tmp/decrypted-sonarcloud-token -inkey ${{ github.workspace }}/.tmp/rsa/rsa_private.pem
|
||||||
- name: "Test with Maven with SonarCloud Scan"
|
- name: "Test with Maven with SonarCloud Scan"
|
||||||
if: ${{ github.repository == 'apache/dubbo' }}
|
if: ${{ github.repository == 'apache/dubbo' }}
|
||||||
timeout-minutes: 70
|
timeout-minutes: 90
|
||||||
env:
|
env:
|
||||||
# Needed to get some information about the pull request, if any
|
# Needed to get some information about the pull request, if any
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
@ -247,7 +246,7 @@ jobs:
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -DtrimStackTrace=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper -Dsonar.coverage.jacoco.xmlReportPaths=dubbo-test/dubbo-dependencies-all/target/site/jacoco-aggregate/jacoco.xml -Dsonar.login=${SONAR_TOKEN}
|
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -DtrimStackTrace=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper -Dsonar.coverage.jacoco.xmlReportPaths=dubbo-test/dubbo-dependencies-all/target/site/jacoco-aggregate/jacoco.xml -Dsonar.login=${SONAR_TOKEN}
|
||||||
- name: "Test with Maven without SonarCloud Scan"
|
- name: "Test with Maven without SonarCloud Scan"
|
||||||
if: ${{ github.repository != 'apache/dubbo' }}
|
if: ${{ github.repository != 'apache/dubbo' }}
|
||||||
timeout-minutes: 70
|
timeout-minutes: 90
|
||||||
run: |
|
run: |
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -DtrimStackTrace=false -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -DtrimStackTrace=false -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
||||||
- name: "Upload coverage result"
|
- name: "Upload coverage result"
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ jobs:
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 8
|
java-version: 21
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
name: "Cache local Maven repository"
|
name: "Cache local Maven repository"
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ header:
|
||||||
- 'dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/EmbeddedZooKeeper.java'
|
- 'dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/EmbeddedZooKeeper.java'
|
||||||
- 'dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/utils/TestSocketUtils.java'
|
- 'dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/utils/TestSocketUtils.java'
|
||||||
- 'dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TriHttp2RemoteFlowController.java'
|
- 'dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TriHttp2RemoteFlowController.java'
|
||||||
|
- 'dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/cors/CorsHeaderFilter.java'
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/serial/SerializingExecutor.java'
|
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/serial/SerializingExecutor.java'
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractAotMojo.java'
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractAotMojo.java'
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractDependencyFilterMojo.java'
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractDependencyFilterMojo.java'
|
||||||
|
|
@ -95,11 +96,15 @@ header:
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/MatchingGroupIdFilter.java'
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/MatchingGroupIdFilter.java'
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java'
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java'
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java'
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java'
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
|
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java'
|
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java'
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java'
|
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java'
|
||||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java'
|
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java'
|
||||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java'
|
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java'
|
||||||
|
- 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java'
|
||||||
|
- 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java'
|
||||||
|
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/protoc/DubboProtocCompilerMojo.java'
|
||||||
|
- 'dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/utils/ProtoTypeMap.java'
|
||||||
|
|
||||||
comment: on-failure
|
comment: on-failure
|
||||||
|
|
||||||
|
|
@ -198,10 +203,26 @@ dependency:
|
||||||
license: Apache-2.0
|
license: Apache-2.0
|
||||||
- name: org.sonatype.plexus:plexus-cipher
|
- name: org.sonatype.plexus:plexus-cipher
|
||||||
license: Apache-2.0
|
license: Apache-2.0
|
||||||
|
- name: com.alibaba.csp:sentinel-apache-dubbo3-adapter
|
||||||
|
license: Apache-2.0
|
||||||
|
- name: com.alibaba.csp:sentinel-transport-simple-http
|
||||||
|
license: Apache-2.0
|
||||||
|
- name: com.alibaba.csp:sentinel-transport-common
|
||||||
|
license: Apache-2.0
|
||||||
|
- name: com.alibaba.csp:sentinel-datasource-extension
|
||||||
|
license: Apache-2.0
|
||||||
|
- name: com.alibaba.csp:sentinel-core
|
||||||
|
license: Apache-2.0
|
||||||
- name: com.google.protobuf:protobuf-java
|
- name: com.google.protobuf:protobuf-java
|
||||||
license: BSD 3-clause
|
license: BSD 3-clause
|
||||||
- name: com.google.protobuf:protobuf-java-util
|
- name: com.google.protobuf:protobuf-java-util
|
||||||
license: BSD 3-clause
|
license: BSD 3-clause
|
||||||
|
- name: org.antlr:antlr4
|
||||||
|
license: BSD 3-clause
|
||||||
|
- name: org.antlr:antlr-runtime
|
||||||
|
license: BSD 3-clause
|
||||||
|
- name: org.antlr:ST4
|
||||||
|
license: BSD 3-clause
|
||||||
# multi license
|
# multi license
|
||||||
- name: org.javassist:javassist
|
- name: org.javassist:javassist
|
||||||
license: Apache-2.0
|
license: Apache-2.0
|
||||||
|
|
|
||||||
20
NOTICE
20
NOTICE
|
|
@ -16,3 +16,23 @@ Copyright 2014 The Netty Project
|
||||||
This product contains code form the t-digest Project:
|
This product contains code form the t-digest Project:
|
||||||
The code for the t-digest was originally authored by Ted Dunning
|
The code for the t-digest was originally authored by Ted Dunning
|
||||||
Adrien Grand contributed the heart of the AVLTreeDigest (https://github.com/jpountz)
|
Adrien Grand contributed the heart of the AVLTreeDigest (https://github.com/jpountz)
|
||||||
|
|
||||||
|
This product contains the following code copied from Maven Protocol Buffers Plugin:
|
||||||
|
dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/protoc/DubboProtocCompilerMojo.java
|
||||||
|
|
||||||
|
Maven Protocol Buffers Plugin
|
||||||
|
=============================
|
||||||
|
Copyright (c) 2016 Maven Protocol Buffers Plugin Authors. All rights reserved.
|
||||||
|
|
||||||
|
This product contains the following code copied from grpc-java-contrib:
|
||||||
|
dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/utils/ProtoTypeMap.java
|
||||||
|
Some portions of this file Copyright (c) 2019, Salesforce.com, Inc. and licensed under the BSD 3-Clause License
|
||||||
|
|
||||||
|
grpc-java-contrib
|
||||||
|
====================
|
||||||
|
Copyright (c) 2019, Salesforce.com, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
236
README.md
236
README.md
|
|
@ -1,187 +1,68 @@
|
||||||
# Apache Dubbo Project
|
# Apache Dubbo Project
|
||||||
|
|
||||||
[](https://github.com/apache/dubbo/actions/workflows/build-and-test-pr.yml)
|
[](https://github.com/apache/dubbo/actions/workflows/build-and-test-pr.yml)
|
||||||
[](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")
|
||||||
|
|
||||||
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.
|
Apache Dubbo is an easy-to-use Web and RPC framework that provides multiple
|
||||||
|
language implementations(Java, [Go](https://github.com/apache/dubbo-go), [Rust](https://github.com/apache/dubbo-rust), [Node.js](https://github.com/apache/dubbo-js), [Web](https://github.com/apache/dubbo-js)) for communication, service discovery, traffic management,
|
||||||
|
observability, security, tools, and best practices for building enterprise-ready microservices.
|
||||||
|
|
||||||
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [Wanted: who's using dubbo](https://github.com/apache/dubbo/discussions/13842), thanks :)
|
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [Wanted: who's using dubbo](https://github.com/apache/dubbo/discussions/13842), thanks :)
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
* Consumer and provider communicate with each other using RPC protocol like triple, tcp, rest, etc.
|
||||||
|
* Consumers automatically trace provider instances registered in registries(Zookeeper, Nacos) and distribute traffic among them by following traffic strategies.
|
||||||
* Transparent interface based RPC
|
* Rich features for monitoring and managing the cluster with dynamic configuration, metrics, tracing, security, and visualized console.
|
||||||
* Intelligent load balancing
|
|
||||||
* Automatic service registration and discovery
|
|
||||||
* High extensibility
|
|
||||||
* Runtime traffic routing
|
|
||||||
* Visualized service governance
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
Follow the instructions below to learn how to:
|
||||||
|
|
||||||
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples.git). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
|
### Programming with lightweight RPC API
|
||||||
|
[5 minutes step-by-step guide](https://dubbo.apache.org/zh-cn/overview/quickstart/rpc/java)
|
||||||
|
|
||||||
```bash
|
Dubbo supports building RPC services with only a few lines of code while depending only on a lightweight SDK (<10MB). The protocol on the wire can be [Triple](https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple/)(fully gRPC compatible and HTTP-friendly), Dubbo2(TCP), REST, or any protocol of your choice.
|
||||||
git clone https://github.com/apache/dubbo-samples.git
|
|
||||||
cd dubbo-samples/1-basic/dubbo-samples-api
|
|
||||||
```
|
|
||||||
|
|
||||||
There's a [README](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/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
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<properties>
|
|
||||||
<dubbo.version>3.2.13-SNAPSHOT</dubbo.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo</artifactId>
|
|
||||||
<version>${dubbo.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-dependencies-zookeeper</artifactId>
|
|
||||||
<version>${dubbo.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Define service interfaces
|
|
||||||
|
|
||||||
```java
|
|
||||||
package org.apache.dubbo.samples.api;
|
|
||||||
|
|
||||||
public interface GreetingsService {
|
|
||||||
String sayHi(String name);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
|
|
||||||
|
|
||||||
### Implement service interface for the provider
|
|
||||||
|
|
||||||
```java
|
|
||||||
package org.apache.dubbo.samples.provider;
|
|
||||||
|
|
||||||
import org.apache.dubbo.samples.api.GreetingsService;
|
|
||||||
|
|
||||||
public class GreetingsServiceImpl implements GreetingsService {
|
|
||||||
@Override
|
|
||||||
public String sayHi(String name) {
|
|
||||||
return "hi, " + name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
|
|
||||||
|
|
||||||
### Start service provider
|
|
||||||
|
|
||||||
```java
|
|
||||||
package org.apache.dubbo.samples.provider;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.dubbo.config.ApplicationConfig;
|
### Building a microservice application with Spring Boot
|
||||||
import org.apache.dubbo.config.RegistryConfig;
|
[5 minutes step-by-step guide](https://dubbo.apache.org/zh-cn/overview/quickstart/microservice)
|
||||||
import org.apache.dubbo.config.ServiceConfig;
|
|
||||||
import org.apache.dubbo.samples.api.GreetingsService;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
It's highly recommended to start your microservice application with the Spring Boot Starter `dubbo-spring-boot-starter` provided by Dubbo. With only a single dependency and yaml file, and optionally a bunch of other useful spring boot starters, you can enable all of the Dubo features like service discovery, observability, tracing, etc.
|
||||||
|
|
||||||
public class Application {
|
Next, learn how to [deploy](https://dubbo.apache.org/zh-cn/overview/tasks/deploy/), [monitor](https://dubbo.apache.org/zh-cn/overview/tasks/observability/), and [manage the traffic](https://dubbo.apache.org/zh-cn/overview/tasks/traffic-management/) of your Dubbo application and cluster.
|
||||||
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
## More Features
|
||||||
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
|
Get more details by visiting the links below to get your hands dirty with some well-designed tasks on our website.
|
||||||
service.setApplication(new ApplicationConfig("first-dubbo-provider"));
|
|
||||||
service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
|
|
||||||
service.setInterface(GreetingsService.class);
|
|
||||||
service.setRef(new GreetingsServiceImpl());
|
|
||||||
service.export();
|
|
||||||
|
|
||||||
System.out.println("dubbo service started");
|
* [Launch a Dubbo project](https://dubbo.apache.org/zh-cn/overview/tasks/develop/template/)
|
||||||
new CountDownLatch(1).await();
|
* [RPC protocols](https://dubbo.apache.org/zh-cn/overview/core-features/protocols/)
|
||||||
}
|
* [Traffic management](https://dubbo.apache.org/zh-cn/overview/core-features/traffic/)
|
||||||
}
|
* [Service discovery](https://dubbo.apache.org/zh-cn/overview/core-features/service-discovery/)
|
||||||
```
|
* [Observability](https://dubbo.apache.org/zh-cn/overview/core-features/observability/)
|
||||||
|
* [Extensibility](https://dubbo.apache.org/zh-cn/overview/core-features/extensibility/)
|
||||||
|
* [Security](https://dubbo.apache.org/zh-cn/overview/core-features/security/)
|
||||||
|
* [Visualized console and control plane](https://dubbo.apache.org/zh-cn/overview/reference/admin/)
|
||||||
|
* [Kubernetes and Service mesh](https://dubbo.apache.org/zh-cn/overview/core-features/service-mesh/)
|
||||||
|
|
||||||
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-spring-xml/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
|
## Which Dubbo version should I use?
|
||||||
|
| **Dubbo3** | **JDK** | **Dependencies** | **Description** |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 3.3.0-beta| 1.8 ~ 17 | [dependency list](https://github.com/apache/dubbo/blob/3.3/dubbo-dependencies-bom/pom.xml#L94) | **- Unstable version** <br/> **- Features** <br/> - Triple - gRPC and cURL compatible.<br/> - Rest-style programming support.<br/> - Spring Boot Starters. |
|
||||||
|
| 3.2.5 | 1.8 ~ 17 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-3.2.5/dubbo-dependencies-bom/pom.xml#L94) | **- Stable version (active)** <br/> **- Features** <br/> - Out-of-box metrics and tracing support.<br/> - Threadpool Isolation<br/> - 30% performance<br/> - Native Image|
|
||||||
|
| 3.1.11 | 1.8 ~ 11 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-3.2.11/dubbo-dependencies-bom/pom.xml#L94) | **Stable version (not active)** |
|
||||||
|
|
||||||
### Build and run the provider
|
| **Dubbo2** | **JDK** | **Dependencies** | **Description** |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 2.7.23 | 1.8 | [dependency list](https://github.com/apache/dubbo/blob/dubbo-2.7.23/dubbo-dependencies-bom/pom.xml#L92) | EOL |
|
||||||
|
| 2.6.x, 2.5.x | 1.6 ~ 1.7 | | EOL |
|
||||||
|
|
||||||
```bash
|
## Contributing
|
||||||
mvn clean package
|
See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||||
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.provider.Application exec:java
|
|
||||||
```
|
|
||||||
|
|
||||||
### Call remote service in the consumer
|
|
||||||
|
|
||||||
```java
|
|
||||||
package org.apache.dubbo.samples.client;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.dubbo.config.ApplicationConfig;
|
|
||||||
import org.apache.dubbo.config.ReferenceConfig;
|
|
||||||
import org.apache.dubbo.config.RegistryConfig;
|
|
||||||
import org.apache.dubbo.samples.api.GreetingsService;
|
|
||||||
|
|
||||||
public class Application {
|
|
||||||
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
|
|
||||||
reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
|
|
||||||
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
|
|
||||||
reference.setInterface(GreetingsService.class);
|
|
||||||
GreetingsService service = reference.get();
|
|
||||||
String message = service.sayHi("dubbo");
|
|
||||||
System.out.println(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
*See [client/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
|
|
||||||
|
|
||||||
### Build and run the consumer
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn clean package
|
|
||||||
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.client.Application exec:java
|
|
||||||
```
|
|
||||||
|
|
||||||
The consumer will print out `hi, dubbo` on the screen.
|
|
||||||
|
|
||||||
|
|
||||||
### Next steps
|
|
||||||
|
|
||||||
* [Your first Dubbo application](https://dubbo.apache.org/en/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
|
|
||||||
* [Dubbo user manual](https://dubbo.apache.org/en/overview/what/) - How to use Dubbo and all its features.
|
|
||||||
* [Dubbo developer guide](https://dubbo.apache.org/en/docs3-v2/java-sdk/) - How to involve in Dubbo development.
|
|
||||||
* [Dubbo admin manual](https://dubbo.apache.org/en/docs/v2.7/admin/ops/) - How to admin and manage Dubbo services.
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is needed to build the master branch)
|
|
||||||
|
|
||||||
```
|
|
||||||
mvn clean install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Recommended Test Environment
|
|
||||||
To avoid intermittent test failures (i.e., flaky tests), it is recommended to have a machine or virtual machine with the following specifications:
|
|
||||||
|
|
||||||
* Minimum of 2CPUs.
|
|
||||||
* Minimum of 2Gb of RAM.
|
|
||||||
|
|
||||||
### How does the Dubbo Community collaborate?
|
### How does the Dubbo Community collaborate?
|
||||||
|
|
||||||
|
|
@ -242,13 +123,39 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?template
|
||||||
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
|
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
* WeChat: apachedubbo
|
||||||
* Mailing list:
|
* DingTalk group: 37290003945
|
||||||
* 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)
|
* Mailing list: [guide](https://dubbo.apache.org/zh-cn/contact/)
|
||||||
|
|
||||||
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
|
|
||||||
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
|
|
||||||
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
||||||
|
* Security issues: please mail to [us](mailto:security@dubbo.apache.org) privately.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||||
|
|
||||||
|
### How can I contribute?
|
||||||
|
|
||||||
|
* Take a look at issues with tags marked [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
|
||||||
|
* Join the discussion on the mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
|
||||||
|
* Answer questions on [issues](https://github.com/apache/dubbo/issues).
|
||||||
|
* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us a pull request.
|
||||||
|
* Review the existing [pull request](https://github.com/apache/dubbo/pulls).
|
||||||
|
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
|
||||||
|
* blog post
|
||||||
|
* translation on documentation
|
||||||
|
* use cases around the integration of Dubbo in enterprise systems.
|
||||||
|
* Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
|
||||||
|
* Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
|
||||||
|
* Other forms of contribution not explicitly enumerated above.
|
||||||
|
* If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
|
||||||
|
|
||||||
|
## Reporting bugs
|
||||||
|
|
||||||
|
Please follow the [template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md) for reporting any issues.
|
||||||
|
|
||||||
|
## Reporting a security vulnerability
|
||||||
|
|
||||||
|
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
|
||||||
|
|
||||||
## Dubbo ecosystem
|
## Dubbo ecosystem
|
||||||
|
|
||||||
|
|
@ -268,5 +175,4 @@ Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org)
|
||||||
* [Erlang](https://github.com/apache/dubbo-erlang)
|
* [Erlang](https://github.com/apache/dubbo-erlang)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
Apache Dubbo is licensed under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
|
||||||
Apache Dubbo software is licensed under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,5 @@ ignore:
|
||||||
- "**/dubbo-test/**"
|
- "**/dubbo-test/**"
|
||||||
- "**/dubbo-compatible/**"
|
- "**/dubbo-compatible/**"
|
||||||
- "**/dubbo-native/**"
|
- "**/dubbo-native/**"
|
||||||
- "**/dubbo-native-plugin/**"
|
|
||||||
- "**/dubbo-common/src/main/java/org/apache/dubbo/common/json/*.java" # internal JSON impl is deprecate, ignore test coverage for them
|
- "**/dubbo-common/src/main/java/org/apache/dubbo/common/json/*.java" # internal JSON impl is deprecate, ignore test coverage for them
|
||||||
- "**/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java" # Deprecated
|
- "**/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java" # Deprecated
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-build-tools</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.deploy.skip>true</maven.deploy.skip>
|
|
||||||
<spotless-maven-plugin.version>2.43.0</spotless-maven-plugin.version>
|
|
||||||
<spotless.action>check</spotless.action>
|
|
||||||
<dubbo-shared-resources.version>1.0.0</dubbo-shared-resources.version>
|
|
||||||
<palantirJavaFormat.version>2.38.0</palantirJavaFormat.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>java11+</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[11,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<!--- newer versions of plugins requires JDK 11 -->
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.diffplug.spotless</groupId>
|
|
||||||
<artifactId>spotless-maven-plugin</artifactId>
|
|
||||||
<version>${spotless-maven-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<java>
|
|
||||||
<palantirJavaFormat>
|
|
||||||
<version>${palantirJavaFormat.version}</version>
|
|
||||||
</palantirJavaFormat>
|
|
||||||
<removeUnusedImports />
|
|
||||||
<importOrder>
|
|
||||||
<file>dubbo-importorder.txt</file>
|
|
||||||
</importOrder>
|
|
||||||
<licenseHeader>
|
|
||||||
<file>checkstyle-header.txt</file>
|
|
||||||
</licenseHeader>
|
|
||||||
</java>
|
|
||||||
<pom>
|
|
||||||
<sortPom>
|
|
||||||
<expandEmptyElements>false</expandEmptyElements>
|
|
||||||
<spaceBeforeCloseEmptyElement>true</spaceBeforeCloseEmptyElement>
|
|
||||||
</sortPom>
|
|
||||||
</pom>
|
|
||||||
<upToDateChecking>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</upToDateChecking>
|
|
||||||
</configuration>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba</groupId>
|
|
||||||
<artifactId>dubbo-shared-resources</artifactId>
|
|
||||||
<version>${dubbo-shared-resources.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>${spotless.action}</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>process-sources</phase>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
|
|
@ -92,6 +92,11 @@
|
||||||
<artifactId>micrometer-tracing-integration-test</artifactId>
|
<artifactId>micrometer-tracing-integration-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-slf4j-impl</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
import org.apache.dubbo.rpc.AdaptiveMetrics;
|
|
||||||
import org.apache.dubbo.rpc.cluster.merger.MergerFactory;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
|
||||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
@ -37,14 +34,9 @@ public class ClusterScopeModelInitializer implements ScopeModelInitializer {
|
||||||
@Override
|
@Override
|
||||||
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
||||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||||
beanFactory.registerBean(MergerFactory.class);
|
|
||||||
beanFactory.registerBean(ClusterUtils.class);
|
beanFactory.registerBean(ClusterUtils.class);
|
||||||
beanFactory.registerBean(AdaptiveMetrics.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeModuleModel(ModuleModel moduleModel) {
|
public void initializeModuleModel(ModuleModel moduleModel) {}
|
||||||
ScopeBeanFactory beanFactory = moduleModel.getBeanFactory();
|
|
||||||
beanFactory.registerBean(MeshRuleManager.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,25 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.remoting.http;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.remoting.http.config.HttpClientConfig;
|
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
|
import org.apache.dubbo.rpc.cluster.merger.MergerFactory;
|
||||||
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||||
|
import org.apache.dubbo.rpc.model.ScopeModelInitializer;
|
||||||
|
|
||||||
public abstract class BaseRestClient<CLIENT> implements RestClient {
|
public class MergeableClusterScopeModelInitializer implements ScopeModelInitializer {
|
||||||
|
@Override
|
||||||
|
public void initializeFrameworkModel(FrameworkModel frameworkModel) {}
|
||||||
|
|
||||||
protected CLIENT client;
|
@Override
|
||||||
|
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
||||||
protected HttpClientConfig clientConfig;
|
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||||
|
beanFactory.registerBean(MergerFactory.class);
|
||||||
public BaseRestClient(HttpClientConfig clientConfig) {
|
|
||||||
this.clientConfig = clientConfig;
|
|
||||||
client = createHttpClient(clientConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract CLIENT createHttpClient(HttpClientConfig clientConfig);
|
@Override
|
||||||
|
public void initializeModuleModel(ModuleModel moduleModel) {}
|
||||||
public HttpClientConfig getClientConfig() {
|
|
||||||
return clientConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CLIENT getClient() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,11 +14,10 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.monitor.support;
|
package org.apache.dubbo.rpc.cluster.filter.support;
|
||||||
|
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
import org.apache.dubbo.common.extension.Activate;
|
||||||
import org.apache.dubbo.rpc.Filter;
|
import org.apache.dubbo.rpc.Filter;
|
||||||
import org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter;
|
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CALLBACK;
|
import static org.apache.dubbo.common.constants.CommonConstants.CALLBACK;
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.dubbo.rpc.cluster.router.mesh;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
|
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
||||||
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||||
|
import org.apache.dubbo.rpc.model.ScopeModelInitializer;
|
||||||
|
|
||||||
|
public class MeshScopeModelInitializer implements ScopeModelInitializer {
|
||||||
|
@Override
|
||||||
|
public void initializeFrameworkModel(FrameworkModel frameworkModel) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeApplicationModel(ApplicationModel applicationModel) {}
|
||||||
|
|
||||||
|
public void initializeModuleModel(ModuleModel moduleModel) {
|
||||||
|
ScopeBeanFactory beanFactory = moduleModel.getBeanFactory();
|
||||||
|
beanFactory.registerBean(MeshRuleManager.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
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.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
|
@ -52,6 +53,7 @@ public class TagStateRouter<T> extends AbstractStateRouter<T> implements Configu
|
||||||
public static final String NAME = "TAG_ROUTER";
|
public static final String NAME = "TAG_ROUTER";
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(TagStateRouter.class);
|
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(TagStateRouter.class);
|
||||||
private static final String RULE_SUFFIX = ".tag-router";
|
private static final String RULE_SUFFIX = ".tag-router";
|
||||||
|
public static final char TAG_SEPERATOR = '|';
|
||||||
|
|
||||||
private volatile TagRouterRule tagRouterRule;
|
private volatile TagRouterRule tagRouterRule;
|
||||||
private String application;
|
private String application;
|
||||||
|
|
@ -119,7 +121,8 @@ public class TagStateRouter<T> extends AbstractStateRouter<T> implements Configu
|
||||||
|
|
||||||
// if we are requesting for a Provider with a specific tag
|
// if we are requesting for a Provider with a specific tag
|
||||||
if (StringUtils.isNotEmpty(tag)) {
|
if (StringUtils.isNotEmpty(tag)) {
|
||||||
Set<String> addresses = tagRouterRuleCopy.getTagnameToAddresses().get(tag);
|
Map<String, Set<String>> tagnameToAddresses = tagRouterRuleCopy.getTagnameToAddresses();
|
||||||
|
Set<String> addresses = selectAddressByTagLevel(tagnameToAddresses, tag, isForceUseTag(invocation));
|
||||||
// filter by dynamic tag group first
|
// filter by dynamic tag group first
|
||||||
if (addresses != null) { // null means tag not set
|
if (addresses != null) { // null means tag not set
|
||||||
result = filterInvoker(invokers, invoker -> addressMatches(invoker.getUrl(), addresses));
|
result = filterInvoker(invokers, invoker -> addressMatches(invoker.getUrl(), addresses));
|
||||||
|
|
@ -336,4 +339,34 @@ public class TagStateRouter<T> extends AbstractStateRouter<T> implements Configu
|
||||||
public void setTagRouterRule(TagRouterRule tagRouterRule) {
|
public void setTagRouterRule(TagRouterRule tagRouterRule) {
|
||||||
this.tagRouterRule = tagRouterRule;
|
this.tagRouterRule = tagRouterRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select addresses by tag with level
|
||||||
|
* <p>
|
||||||
|
* example:
|
||||||
|
* selector=beta|team1|partner1
|
||||||
|
* step1.select tagAddresses with selector=beta|team1|partner1, if result is empty, then run step2
|
||||||
|
* step2.select tagAddresses with selector=beta|team1, if result is empty, then run step3
|
||||||
|
* step3.select tagAddresses with selector=beta, if result is empty, result is null
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tagAddresses
|
||||||
|
* @param tagSelector eg: beta|team1|partner1
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Set<String> selectAddressByTagLevel(
|
||||||
|
Map<String, Set<String>> tagAddresses, String tagSelector, boolean isForce) {
|
||||||
|
if (isForce || StringUtils.isNotContains(tagSelector, TAG_SEPERATOR)) {
|
||||||
|
return tagAddresses.get(tagSelector);
|
||||||
|
}
|
||||||
|
String[] selectors = StringUtils.split(tagSelector, TAG_SEPERATOR);
|
||||||
|
for (int i = selectors.length; i > 0; i--) {
|
||||||
|
String selectorTmp = StringUtils.join(selectors, TAG_SEPERATOR, 0, i);
|
||||||
|
Set<String> addresses = tagAddresses.get(selectorTmp);
|
||||||
|
if (CollectionUtils.isNotEmpty(addresses)) {
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.ConfigUtils;
|
import org.apache.dubbo.common.utils.ConfigUtils;
|
||||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||||
|
import org.apache.dubbo.rpc.Constants;
|
||||||
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;
|
||||||
|
|
@ -42,8 +43,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_GROUP_MERGE;
|
|
||||||
import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
|
|
||||||
import static org.apache.dubbo.rpc.Constants.MERGER_KEY;
|
import static org.apache.dubbo.rpc.Constants.MERGER_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -95,7 +94,7 @@ public class MergeableClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
Map<String, Result> results = new HashMap<>();
|
Map<String, Result> results = new HashMap<>();
|
||||||
for (final Invoker<T> invoker : invokers) {
|
for (final Invoker<T> invoker : invokers) {
|
||||||
RpcInvocation subInvocation = new RpcInvocation(invocation, invoker);
|
RpcInvocation subInvocation = new RpcInvocation(invocation, invoker);
|
||||||
subInvocation.setAttachment(ASYNC_KEY, "true");
|
subInvocation.setAttachment(Constants.ASYNC_KEY, "true");
|
||||||
try {
|
try {
|
||||||
results.put(invoker.getUrl().getServiceKey(), invokeWithContext(invoker, subInvocation));
|
results.put(invoker.getUrl().getServiceKey(), invokeWithContext(invoker, subInvocation));
|
||||||
} catch (RpcException e) {
|
} catch (RpcException e) {
|
||||||
|
|
@ -123,7 +122,7 @@ public class MergeableClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||||
Result r = asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
|
Result r = asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||||
if (r.hasException()) {
|
if (r.hasException()) {
|
||||||
log.error(
|
log.error(
|
||||||
CLUSTER_FAILED_GROUP_MERGE,
|
LoggerCodeConstants.CLUSTER_FAILED_GROUP_MERGE,
|
||||||
"Invoke " + getGroupDescFromServiceKey(entry.getKey()) + " failed: "
|
"Invoke " + getGroupDescFromServiceKey(entry.getKey()) + " failed: "
|
||||||
+ r.getException().getMessage(),
|
+ r.getException().getMessage(),
|
||||||
"",
|
"",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.common.utils.ConfigUtils;
|
import org.apache.dubbo.common.utils.ConfigUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.InvokeMode;
|
import org.apache.dubbo.rpc.InvokeMode;
|
||||||
|
|
@ -47,8 +48,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
|
||||||
public class MockClusterInvoker<T> implements ClusterInvoker<T> {
|
public class MockClusterInvoker<T> implements ClusterInvoker<T> {
|
||||||
|
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MockClusterInvoker.class);
|
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MockClusterInvoker.class);
|
||||||
private static final boolean setFutureWhenSync =
|
private static final boolean setFutureWhenSync = Boolean.parseBoolean(SystemPropertyConfigUtils.getSystemProperty(
|
||||||
Boolean.parseBoolean(System.getProperty(CommonConstants.SET_FUTURE_IN_SYNC_MODE, "true"));
|
CommonConstants.ThirdPartyProperty.SET_FUTURE_IN_SYNC_MODE, "true"));
|
||||||
|
|
||||||
private final Directory<T> directory;
|
private final Directory<T> directory;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
callback-consumer-context=org.apache.dubbo.rpc.cluster.filter.support.CallbackConsumerContextFilter
|
||||||
|
|
@ -8,4 +8,4 @@ forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster
|
||||||
available=org.apache.dubbo.rpc.cluster.support.AvailableCluster
|
available=org.apache.dubbo.rpc.cluster.support.AvailableCluster
|
||||||
mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster
|
mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster
|
||||||
broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster
|
broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster
|
||||||
zone-aware=org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster
|
zone-aware=org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
consumercontext=org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter
|
consumercontext=org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter
|
||||||
consumer-classloader=org.apache.dubbo.rpc.cluster.filter.support.ConsumerClassLoaderFilter
|
consumer-classloader=org.apache.dubbo.rpc.cluster.filter.support.ConsumerClassLoaderFilter
|
||||||
router-snapshot=org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter
|
router-snapshot=org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter
|
||||||
observationsender=org.apache.dubbo.rpc.cluster.filter.support.ObservationSenderFilter
|
|
||||||
metricsClusterFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsClusterFilter
|
|
||||||
metricsConsumerFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsConsumerFilter
|
metricsConsumerFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsConsumerFilter
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
attachment=org.apache.dubbo.rpc.cluster.router.condition.matcher.attachment.AttachmentConditionMatcherFactory
|
attachment=org.apache.dubbo.rpc.cluster.router.condition.matcher.attachment.AttachmentConditionMatcherFactory
|
||||||
argument=org.apache.dubbo.rpc.cluster.router.condition.matcher.argument.ArgumentConditionMatcherFactory
|
argument=org.apache.dubbo.rpc.cluster.router.condition.matcher.argument.ArgumentConditionMatcherFactory
|
||||||
param=org.apache.dubbo.rpc.cluster.router.condition.matcher.param.UrlParamConditionMatcherFactory
|
param=org.apache.dubbo.rpc.cluster.router.condition.matcher.param.UrlParamConditionMatcherFactory
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
tag=org.apache.dubbo.rpc.cluster.router.tag.TagStateRouterFactory
|
mock=org.apache.dubbo.rpc.cluster.router.mock.MockStateRouterFactory
|
||||||
condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionStateRouterFactory
|
condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionStateRouterFactory
|
||||||
service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceStateRouterFactory
|
service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceStateRouterFactory
|
||||||
app=org.apache.dubbo.rpc.cluster.router.condition.config.AppStateRouterFactory
|
app=org.apache.dubbo.rpc.cluster.router.condition.config.AppStateRouterFactory
|
||||||
provider-app=org.apache.dubbo.rpc.cluster.router.condition.config.ProviderAppStateRouterFactory
|
provider-app=org.apache.dubbo.rpc.cluster.router.condition.config.ProviderAppStateRouterFactory
|
||||||
script-app=org.apache.dubbo.rpc.cluster.router.script.config.AppScriptRouterFactory
|
|
||||||
mock=org.apache.dubbo.rpc.cluster.router.mock.MockStateRouterFactory
|
|
||||||
standard-mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.StandardMeshRuleRouterFactory
|
standard-mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.StandardMeshRuleRouterFactory
|
||||||
|
script-app=org.apache.dubbo.rpc.cluster.router.script.config.AppScriptRouterFactory
|
||||||
|
tag=org.apache.dubbo.rpc.cluster.router.tag.TagStateRouterFactory
|
||||||
|
|
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
dubbo-cluster=org.apache.dubbo.rpc.cluster.ClusterScopeModelInitializer
|
dubbo-cluster=org.apache.dubbo.rpc.cluster.ClusterScopeModelInitializer
|
||||||
|
dubbo-cluster-mergeable=org.apache.dubbo.rpc.cluster.MergeableClusterScopeModelInitializer
|
||||||
|
mesh=org.apache.dubbo.rpc.cluster.router.mesh.MeshScopeModelInitializer
|
||||||
|
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
|
|
||||||
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
|
|
||||||
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
|
|
||||||
import org.apache.dubbo.common.url.component.ServiceConfigURL;
|
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
|
||||||
import org.apache.dubbo.rpc.RpcInvocation;
|
|
||||||
import org.apache.dubbo.rpc.cluster.filter.DemoService;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.config.AppStateRouter;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.config.ListenableStateRouter;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.config.ServiceStateRouter;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshAppRuleListener;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
|
|
||||||
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.MESH_RULE_DATA_ID_SUFFIX;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
class RouterChainTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify the router and state router loaded by default
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testBuildRouterChain() {
|
|
||||||
RouterChain<DemoService> routerChain = createRouterChanin();
|
|
||||||
Assertions.assertEquals(0, routerChain.getRouters().size());
|
|
||||||
Assertions.assertEquals(7, routerChain.getStateRouters().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private RouterChain<DemoService> createRouterChanin() {
|
|
||||||
Map<String, String> parameters = new HashMap<>();
|
|
||||||
parameters.put(INTERFACE_KEY, DemoService.class.getName());
|
|
||||||
parameters.put("registry", "zookeeper");
|
|
||||||
URL url = new ServiceConfigURL("dubbo", "127.0.0.1", 20881, DemoService.class.getName(), parameters);
|
|
||||||
|
|
||||||
RouterChain<DemoService> routerChain = RouterChain.buildChain(DemoService.class, url);
|
|
||||||
return routerChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testRoute() {
|
|
||||||
RouterChain<DemoService> routerChain = createRouterChanin();
|
|
||||||
|
|
||||||
// mockInvoker will be filtered out by MockInvokersSelector
|
|
||||||
Invoker<DemoService> mockInvoker = createMockInvoker();
|
|
||||||
|
|
||||||
// invoker1 will be filtered out by MeshStateRouter
|
|
||||||
Map<String, String> map1 = new HashMap<>();
|
|
||||||
map1.put("env-sign", "yyyyyyy");
|
|
||||||
Invoker<DemoService> invoker1 = createNormalInvoker(map1);
|
|
||||||
|
|
||||||
// invoker2 will be filtered out by TagStateRouter
|
|
||||||
Map<String, String> map2 = new HashMap<>();
|
|
||||||
map2.put("env-sign", "xxx");
|
|
||||||
map2.put("tag1", "hello");
|
|
||||||
Invoker<DemoService> invoker2 = createNormalInvoker(map2);
|
|
||||||
|
|
||||||
// invoker3 will be filtered out by AppStateRouter
|
|
||||||
Map<String, String> map3 = new HashMap<>();
|
|
||||||
map3.put("env-sign", "xxx");
|
|
||||||
map3.put("tag1", "hello");
|
|
||||||
map3.put(TAG_KEY, "TAG_");
|
|
||||||
Invoker<DemoService> invoker3 = createNormalInvoker(map3);
|
|
||||||
|
|
||||||
// invoker4 will be filtered out by ServiceStateRouter
|
|
||||||
Map<String, String> map4 = new HashMap<>();
|
|
||||||
map4.put("env-sign", "xxx");
|
|
||||||
map4.put("tag1", "hello");
|
|
||||||
map4.put(TAG_KEY, "TAG_");
|
|
||||||
map4.put("timeout", "5000");
|
|
||||||
Invoker<DemoService> invoker4 = createNormalInvoker(map4);
|
|
||||||
|
|
||||||
// invoker5 is the only one returned at the end that is not filtered out
|
|
||||||
Map<String, String> map5 = new HashMap<>();
|
|
||||||
map5.put("env-sign", "xxx");
|
|
||||||
map5.put("tag1", "hello");
|
|
||||||
map5.put(TAG_KEY, "TAG_");
|
|
||||||
map5.put("timeout", "5000");
|
|
||||||
map5.put("serialization", "hessian2");
|
|
||||||
Invoker<DemoService> invoker5 = createNormalInvoker(map5);
|
|
||||||
|
|
||||||
BitList<Invoker<DemoService>> invokers =
|
|
||||||
new BitList<>(Arrays.asList(mockInvoker, invoker1, invoker2, invoker3, invoker4, invoker5));
|
|
||||||
routerChain.setInvokers(invokers, () -> {});
|
|
||||||
|
|
||||||
// mesh rule for MeshStateRouter
|
|
||||||
MeshRuleManager meshRuleManager =
|
|
||||||
mockInvoker.getUrl().getOrDefaultModuleModel().getBeanFactory().getBean(MeshRuleManager.class);
|
|
||||||
ConcurrentHashMap<String, MeshAppRuleListener> appRuleListeners = meshRuleManager.getAppRuleListeners();
|
|
||||||
MeshAppRuleListener meshAppRuleListener =
|
|
||||||
appRuleListeners.get(invoker1.getUrl().getRemoteApplication());
|
|
||||||
ConfigChangedEvent configChangedEvent = new ConfigChangedEvent(
|
|
||||||
"demo-route" + MESH_RULE_DATA_ID_SUFFIX,
|
|
||||||
DynamicConfiguration.DEFAULT_GROUP,
|
|
||||||
MESH_RULE1 + "---\n" + MESH_RULE2,
|
|
||||||
ConfigChangeType.ADDED);
|
|
||||||
meshAppRuleListener.process(configChangedEvent);
|
|
||||||
|
|
||||||
// condition rule for AppStateRouter&ServiceStateRouter
|
|
||||||
ListenableStateRouter serviceRouter = routerChain.getStateRouters().stream()
|
|
||||||
.filter(s -> s instanceof ServiceStateRouter)
|
|
||||||
.map(s -> (ListenableStateRouter) s)
|
|
||||||
.findAny()
|
|
||||||
.orElse(null);
|
|
||||||
ConfigChangedEvent serviceConditionEvent = new ConfigChangedEvent(
|
|
||||||
DynamicConfiguration.getRuleKey(mockInvoker.getUrl()) + ".condition-router",
|
|
||||||
DynamicConfiguration.DEFAULT_GROUP,
|
|
||||||
SERVICE_CONDITION_RULE,
|
|
||||||
ConfigChangeType.ADDED);
|
|
||||||
serviceRouter.process(serviceConditionEvent);
|
|
||||||
|
|
||||||
ListenableStateRouter appRouter = routerChain.getStateRouters().stream()
|
|
||||||
.filter(s -> s instanceof AppStateRouter)
|
|
||||||
.map(s -> (ListenableStateRouter) s)
|
|
||||||
.findAny()
|
|
||||||
.orElse(null);
|
|
||||||
ConfigChangedEvent appConditionEvent = new ConfigChangedEvent(
|
|
||||||
"app.condition-router", DynamicConfiguration.DEFAULT_GROUP, APP_CONDITION_RULE, ConfigChangeType.ADDED);
|
|
||||||
appRouter.process(appConditionEvent);
|
|
||||||
|
|
||||||
// prepare consumerUrl and RpcInvocation
|
|
||||||
URL consumerUrl = URL.valueOf("consumer://localhost/DemoInterface?remote.application=app1");
|
|
||||||
RpcInvocation rpcInvocation = new RpcInvocation();
|
|
||||||
rpcInvocation.setServiceName("DemoService");
|
|
||||||
rpcInvocation.setObjectAttachment("trafficLabel", "xxx");
|
|
||||||
rpcInvocation.setObjectAttachment(TAG_KEY, "TAG_");
|
|
||||||
|
|
||||||
RpcContext.getServiceContext().setNeedPrintRouterSnapshot(true);
|
|
||||||
RouterSnapshotSwitcher routerSnapshotSwitcher =
|
|
||||||
FrameworkModel.defaultModel().getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
|
||||||
routerSnapshotSwitcher.addEnabledService("org.apache.dubbo.demo.DemoService");
|
|
||||||
// route
|
|
||||||
List<Invoker<DemoService>> result = routerChain
|
|
||||||
.getSingleChain(consumerUrl, invokers, rpcInvocation)
|
|
||||||
.route(consumerUrl, invokers, rpcInvocation);
|
|
||||||
Assertions.assertEquals(result.size(), 1);
|
|
||||||
Assertions.assertTrue(result.contains(invoker5));
|
|
||||||
|
|
||||||
String snapshotLog =
|
|
||||||
"[ Parent (Input: 6) (Current Node Output: 6) (Chain Node Output: 1) ] Input: localhost:9103,localhost:9103,localhost:9103,localhost:9103,localhost:9103 -> Chain Node Output: localhost:9103...\n"
|
|
||||||
+ " [ MockInvokersSelector (Input: 6) (Current Node Output: 5) (Chain Node Output: 1) Router message: invocation.need.mock not set. Return normal Invokers. ] Current Node Output: localhost:9103,localhost:9103,localhost:9103,localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ StandardMeshRuleRouter (Input: 5) (Current Node Output: 4) (Chain Node Output: 1) Router message: Match App: app Subset: isolation ] Current Node Output: localhost:9103,localhost:9103,localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ TagStateRouter (Input: 4) (Current Node Output: 3) (Chain Node Output: 1) Router message: Disable Tag Router. Reason: tagRouterRule is invalid or disabled ] Current Node Output: localhost:9103,localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ ServiceStateRouter (Input: 3) (Current Node Output: 3) (Chain Node Output: 1) Router message: null ] Current Node Output: localhost:9103,localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ ConditionStateRouter (Input: 3) (Current Node Output: 2) (Chain Node Output: 2) Router message: Match return. ] Current Node Output: localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ ProviderAppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 1) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ AppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 1) Router message: null ] Current Node Output: localhost:9103,localhost:9103\n"
|
|
||||||
+ " [ ConditionStateRouter (Input: 2) (Current Node Output: 1) (Chain Node Output: 1) Router message: Match return. ] Current Node Output: localhost:9103\n"
|
|
||||||
+ " [ AppScriptStateRouter (Input: 1) (Current Node Output: 1) (Chain Node Output: 1) Router message: Directly return from script router. Reason: Invokers from previous router is empty or script is not enabled. Script rule is: null ] Current Node Output: localhost:9103";
|
|
||||||
String[] snapshot = routerSnapshotSwitcher.cloneSnapshot();
|
|
||||||
Assertions.assertTrue(snapshot[0].contains(snapshotLog));
|
|
||||||
|
|
||||||
RpcContext.getServiceContext().setNeedPrintRouterSnapshot(false);
|
|
||||||
result = routerChain
|
|
||||||
.getSingleChain(consumerUrl, invokers, rpcInvocation)
|
|
||||||
.route(consumerUrl, invokers, rpcInvocation);
|
|
||||||
Assertions.assertEquals(result.size(), 1);
|
|
||||||
Assertions.assertTrue(result.contains(invoker5));
|
|
||||||
|
|
||||||
routerChain.destroy();
|
|
||||||
Assertions.assertEquals(routerChain.getRouters().size(), 0);
|
|
||||||
Assertions.assertEquals(routerChain.getStateRouters().size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Invoker<DemoService> createMockInvoker() {
|
|
||||||
URL url = URL.valueOf("mock://localhost:9103/DemoInterface?remote.application=app");
|
|
||||||
Invoker<DemoService> invoker = Mockito.mock(Invoker.class);
|
|
||||||
when(invoker.getUrl()).thenReturn(url);
|
|
||||||
return invoker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Invoker<DemoService> createNormalInvoker(Map<String, String> parameters) {
|
|
||||||
URL url = URL.valueOf("dubbo://localhost:9103/DemoInterface?remote.application=app");
|
|
||||||
if (CollectionUtils.isNotEmptyMap(parameters)) {
|
|
||||||
url = url.addParameters(parameters);
|
|
||||||
}
|
|
||||||
Invoker<DemoService> invoker = Mockito.mock(Invoker.class);
|
|
||||||
when(invoker.getUrl()).thenReturn(url);
|
|
||||||
return invoker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String MESH_RULE1 =
|
|
||||||
"apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
|
|
||||||
+ "metadata: { name: demo-route }\n"
|
|
||||||
+ "spec:\n"
|
|
||||||
+ " host: demo\n"
|
|
||||||
+ " subsets:\n"
|
|
||||||
+ " - labels: { env-sign: xxx, tag1: hello }\n"
|
|
||||||
+ " name: isolation\n"
|
|
||||||
+ " - labels: { env-sign: yyy }\n"
|
|
||||||
+ " name: testing-trunk\n"
|
|
||||||
+ " - labels: { env-sign: zzz }\n"
|
|
||||||
+ " name: testing\n"
|
|
||||||
+ " trafficPolicy:\n"
|
|
||||||
+ " loadBalancer: { simple: ROUND_ROBIN }\n"
|
|
||||||
+ "\n";
|
|
||||||
|
|
||||||
private static final String MESH_RULE2 =
|
|
||||||
"apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
|
|
||||||
+ "metadata: { name: demo-route }\n"
|
|
||||||
+ "spec:\n"
|
|
||||||
+ " dubbo:\n"
|
|
||||||
+ " - routedetail:\n"
|
|
||||||
+ " - match:\n"
|
|
||||||
+ " - attachments: \n"
|
|
||||||
+ " dubboContext: {trafficLabel: {regex: xxx}}\n"
|
|
||||||
+ " name: xxx-project\n"
|
|
||||||
+ " route:\n"
|
|
||||||
+ " - destination: {host: demo, subset: isolation}\n"
|
|
||||||
+ " services:\n"
|
|
||||||
+ " - {regex: DemoService}\n"
|
|
||||||
+ " hosts: [demo]\n";
|
|
||||||
|
|
||||||
private static final String APP_CONDITION_RULE = "scope: application\n" + "force: true\n"
|
|
||||||
+ "runtime: false\n"
|
|
||||||
+ "enabled: true\n"
|
|
||||||
+ "priority: 1\n"
|
|
||||||
+ "key: demo-consumer\n"
|
|
||||||
+ "conditions:\n"
|
|
||||||
+ "- => serialization=hessian2";
|
|
||||||
|
|
||||||
private static final String SERVICE_CONDITION_RULE = "scope: service\n" + "force: true\n"
|
|
||||||
+ "runtime: false\n"
|
|
||||||
+ "enabled: true\n"
|
|
||||||
+ "priority: 1\n"
|
|
||||||
+ "key: org.apache.dubbo.demo.DemoService\n"
|
|
||||||
+ "conditions:\n"
|
|
||||||
+ "- => timeout=5000";
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.filter;
|
|
||||||
|
|
||||||
import org.apache.dubbo.config.ApplicationConfig;
|
|
||||||
import org.apache.dubbo.config.TracingConfig;
|
|
||||||
import org.apache.dubbo.rpc.AppResponse;
|
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.RpcInvocation;
|
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
|
||||||
|
|
||||||
import io.micrometer.tracing.test.SampleTestRunner;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
|
|
||||||
import static org.mockito.BDDMockito.given;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
abstract class AbstractObservationFilterTest extends SampleTestRunner {
|
|
||||||
|
|
||||||
ApplicationModel applicationModel;
|
|
||||||
RpcInvocation invocation;
|
|
||||||
|
|
||||||
BaseFilter filter;
|
|
||||||
|
|
||||||
Invoker<?> invoker = mock(Invoker.class);
|
|
||||||
|
|
||||||
static final String INTERFACE_NAME = "org.apache.dubbo.MockInterface";
|
|
||||||
static final String METHOD_NAME = "mockMethod";
|
|
||||||
static final String GROUP = "mockGroup";
|
|
||||||
static final String VERSION = "1.0.0";
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
public void teardown() {
|
|
||||||
if (applicationModel != null) {
|
|
||||||
applicationModel.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract BaseFilter createFilter(ApplicationModel applicationModel);
|
|
||||||
|
|
||||||
void setupConfig() {
|
|
||||||
ApplicationConfig config = new ApplicationConfig();
|
|
||||||
config.setName("MockObservations");
|
|
||||||
|
|
||||||
applicationModel = ApplicationModel.defaultModel();
|
|
||||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
|
||||||
|
|
||||||
invocation = new RpcInvocation(new MockInvocation());
|
|
||||||
invocation.addInvokedInvoker(invoker);
|
|
||||||
|
|
||||||
applicationModel.getBeanFactory().registerBean(getObservationRegistry());
|
|
||||||
TracingConfig tracingConfig = new TracingConfig();
|
|
||||||
tracingConfig.setEnabled(true);
|
|
||||||
applicationModel.getApplicationConfigManager().setTracing(tracingConfig);
|
|
||||||
|
|
||||||
filter = createFilter(applicationModel);
|
|
||||||
|
|
||||||
given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
|
|
||||||
|
|
||||||
initParam();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initParam() {
|
|
||||||
invocation.setTargetServiceUniqueName(GROUP + "/" + INTERFACE_NAME + ":" + VERSION);
|
|
||||||
invocation.setMethodName(METHOD_NAME);
|
|
||||||
invocation.setParameterTypes(new Class[] {String.class});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -18,12 +18,10 @@ package org.apache.dubbo.rpc.cluster.router.tag;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
|
||||||
import org.apache.dubbo.common.utils.Holder;
|
import org.apache.dubbo.common.utils.Holder;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcInvocation;
|
import org.apache.dubbo.rpc.RpcInvocation;
|
||||||
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
|
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
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.tag.model.TagRouterRule;
|
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule;
|
||||||
|
|
@ -32,10 +30,12 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -48,7 +48,6 @@ class TagStateRouterTest {
|
||||||
private URL url;
|
private URL url;
|
||||||
private ModuleModel originModel;
|
private ModuleModel originModel;
|
||||||
private ModuleModel moduleModel;
|
private ModuleModel moduleModel;
|
||||||
private Set<TracingContextProvider> tracingContextProviders;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() {
|
public void setup() {
|
||||||
|
|
@ -59,11 +58,6 @@ class TagStateRouterTest {
|
||||||
ScopeBeanFactory beanFactory = Mockito.spy(originBeanFactory);
|
ScopeBeanFactory beanFactory = Mockito.spy(originBeanFactory);
|
||||||
when(moduleModel.getBeanFactory()).thenReturn(beanFactory);
|
when(moduleModel.getBeanFactory()).thenReturn(beanFactory);
|
||||||
|
|
||||||
ExtensionLoader<TracingContextProvider> extensionLoader = Mockito.mock(ExtensionLoader.class);
|
|
||||||
tracingContextProviders = new HashSet<>();
|
|
||||||
when(extensionLoader.getSupportedExtensionInstances()).thenReturn(tracingContextProviders);
|
|
||||||
when(moduleModel.getExtensionLoader(TracingContextProvider.class)).thenReturn(extensionLoader);
|
|
||||||
|
|
||||||
url = URL.valueOf("test://localhost/DemoInterface").setScopeModel(moduleModel);
|
url = URL.valueOf("test://localhost/DemoInterface").setScopeModel(moduleModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,4 +258,44 @@ class TagStateRouterTest {
|
||||||
TagRouterRule tagRouterRule = TagRuleParser.parse(tagRouterRuleConfig);
|
TagRouterRule tagRouterRule = TagRuleParser.parse(tagRouterRuleConfig);
|
||||||
return tagRouterRule;
|
return tagRouterRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tagMultiLevelTest() {
|
||||||
|
String tagSelector = "beta|team1|partner1";
|
||||||
|
Set<String> address1 = Sets.newHashSet("192.168.5.1:20880");
|
||||||
|
Map<String, Set<String>> tagAddresses = new HashMap<>();
|
||||||
|
tagAddresses.put("beta", address1);
|
||||||
|
Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
|
||||||
|
Set<String> address2 = Sets.newHashSet("192.168.5.2:20880");
|
||||||
|
tagAddresses.put("beta|team1", address2);
|
||||||
|
Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
|
||||||
|
Set<String> address3 = Sets.newHashSet("192.168.5.3:20880");
|
||||||
|
tagAddresses.put("beta|team1|partner1", address3);
|
||||||
|
Assertions.assertEquals(address3, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
|
||||||
|
tagSelector = "beta";
|
||||||
|
Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
tagSelector = "beta|team1";
|
||||||
|
Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
tagSelector = "beta|team1|partner1";
|
||||||
|
Assertions.assertEquals(address3, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
|
||||||
|
tagSelector = "beta2";
|
||||||
|
Assertions.assertNull(TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
tagSelector = "beta|team2";
|
||||||
|
Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
tagSelector = "beta|team1|partner2";
|
||||||
|
Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tagLevelForceTest() {
|
||||||
|
Set<String> addresses = Sets.newHashSet("192.168.1.223:20880");
|
||||||
|
Map<String, Set<String>> tagAddresses = new HashMap<>();
|
||||||
|
tagAddresses.put("beta", addresses);
|
||||||
|
Set<String> selectedAddresses = TagStateRouter.selectAddressByTagLevel(tagAddresses, "beta", true);
|
||||||
|
Assertions.assertEquals(addresses, selectedAddresses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
|
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.same;
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
|
|
@ -580,25 +579,5 @@ class AbstractClusterInvokerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test mock invoker selector works as expected
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testMockedInvokerSelect() {
|
|
||||||
initlistsize5();
|
|
||||||
invokers.add(mockedInvoker1);
|
|
||||||
|
|
||||||
initDic();
|
|
||||||
|
|
||||||
RpcInvocation mockedInvocation = new RpcInvocation();
|
|
||||||
mockedInvocation.setMethodName("sayHello");
|
|
||||||
mockedInvocation.setAttachment(INVOCATION_NEED_MOCK, "true");
|
|
||||||
List<Invoker<IHelloService>> mockedInvokers = dic.list(mockedInvocation);
|
|
||||||
Assertions.assertEquals(1, mockedInvokers.size());
|
|
||||||
|
|
||||||
List<Invoker<IHelloService>> invokers = dic.list(invocation);
|
|
||||||
Assertions.assertEquals(5, invokers.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface IHelloService {}
|
public static interface IHelloService {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.support;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
public interface DemoServiceA {
|
public interface DemoServiceA {
|
||||||
String methodA();
|
String methodA();
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.support;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default mock service for DemoServiceA
|
* default mock service for DemoServiceA
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.support;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
public interface DemoServiceB {
|
public interface DemoServiceB {
|
||||||
String methodB();
|
String methodB();
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.support;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default mock service for DemoServiceA
|
* default mock service for DemoServiceA
|
||||||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
|
import org.apache.dubbo.common.logger.Level;
|
||||||
import org.apache.dubbo.common.utils.DubboAppender;
|
import org.apache.dubbo.common.utils.DubboAppender;
|
||||||
import org.apache.dubbo.common.utils.LogUtil;
|
import org.apache.dubbo.common.utils.LogUtil;
|
||||||
import org.apache.dubbo.rpc.AppResponse;
|
import org.apache.dubbo.rpc.AppResponse;
|
||||||
|
|
@ -34,7 +35,6 @@ import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.log4j.Level;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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.rpc.cluster.support;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.extension.SPI;
|
||||||
|
|
||||||
|
@SPI
|
||||||
|
public interface Greeting {
|
||||||
|
String hello();
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,6 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.config.mock;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
public class GreetingMock1 {}
|
public class GreetingMock1 {}
|
||||||
|
|
@ -14,9 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.config.mock;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
import org.apache.dubbo.config.api.Greeting;
|
|
||||||
|
|
||||||
public class GreetingMock2 implements Greeting {
|
public class GreetingMock2 implements Greeting {
|
||||||
private GreetingMock2() {}
|
private GreetingMock2() {}
|
||||||
|
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* 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.rpc.cluster.support;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||||
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
|
import org.apache.dubbo.rpc.Result;
|
||||||
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
|
import org.apache.dubbo.rpc.RpcInvocation;
|
||||||
|
import org.apache.dubbo.rpc.cluster.LoadBalance;
|
||||||
|
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||||
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_CONNECTIVITY_VALIDATION;
|
||||||
|
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY;
|
||||||
|
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
|
||||||
|
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractClusterInvokerTest
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
class MockAbstractClusterInvokerTest {
|
||||||
|
List<Invoker<IHelloService>> invokers = new ArrayList<Invoker<IHelloService>>();
|
||||||
|
List<Invoker<IHelloService>> selectedInvokers = new ArrayList<Invoker<IHelloService>>();
|
||||||
|
AbstractClusterInvoker<IHelloService> cluster;
|
||||||
|
AbstractClusterInvoker<IHelloService> cluster_nocheck;
|
||||||
|
StaticDirectory<IHelloService> dic;
|
||||||
|
RpcInvocation invocation = new RpcInvocation();
|
||||||
|
URL url = URL.valueOf(
|
||||||
|
"registry://localhost:9090/org.apache.dubbo.rpc.cluster.support.AbstractClusterInvokerTest.IHelloService?refer="
|
||||||
|
+ URL.encode("application=abstractClusterInvokerTest"));
|
||||||
|
URL consumerUrl = URL.valueOf(
|
||||||
|
"dubbo://localhost?application=abstractClusterInvokerTest&refer=application%3DabstractClusterInvokerTest");
|
||||||
|
|
||||||
|
Invoker<IHelloService> invoker1;
|
||||||
|
Invoker<IHelloService> invoker2;
|
||||||
|
Invoker<IHelloService> invoker3;
|
||||||
|
Invoker<IHelloService> invoker4;
|
||||||
|
Invoker<IHelloService> invoker5;
|
||||||
|
Invoker<IHelloService> mockedInvoker1;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setUpBeforeClass() throws Exception {
|
||||||
|
System.setProperty(ENABLE_CONNECTIVITY_VALIDATION, "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void teardown() throws Exception {
|
||||||
|
RpcContext.removeContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterClass() {
|
||||||
|
System.clearProperty(ENABLE_CONNECTIVITY_VALIDATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
ApplicationModel.defaultModel().getBeanFactory().registerBean(MetricsDispatcher.class);
|
||||||
|
Map<String, Object> attributes = new HashMap<>();
|
||||||
|
attributes.put("application", "abstractClusterInvokerTest");
|
||||||
|
url = url.putAttribute(REFER_KEY, attributes);
|
||||||
|
|
||||||
|
invocation.setMethodName("sayHello");
|
||||||
|
|
||||||
|
invoker1 = mock(Invoker.class);
|
||||||
|
invoker2 = mock(Invoker.class);
|
||||||
|
invoker3 = mock(Invoker.class);
|
||||||
|
invoker4 = mock(Invoker.class);
|
||||||
|
invoker5 = mock(Invoker.class);
|
||||||
|
mockedInvoker1 = mock(Invoker.class);
|
||||||
|
|
||||||
|
URL turl = URL.valueOf("test://test:11/test");
|
||||||
|
|
||||||
|
given(invoker1.isAvailable()).willReturn(false);
|
||||||
|
given(invoker1.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(invoker1.getUrl()).willReturn(turl.setPort(1).addParameter("name", "invoker1"));
|
||||||
|
|
||||||
|
given(invoker2.isAvailable()).willReturn(true);
|
||||||
|
given(invoker2.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(invoker2.getUrl()).willReturn(turl.setPort(2).addParameter("name", "invoker2"));
|
||||||
|
|
||||||
|
given(invoker3.isAvailable()).willReturn(false);
|
||||||
|
given(invoker3.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(invoker3.getUrl()).willReturn(turl.setPort(3).addParameter("name", "invoker3"));
|
||||||
|
|
||||||
|
given(invoker4.isAvailable()).willReturn(true);
|
||||||
|
given(invoker4.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(invoker4.getUrl()).willReturn(turl.setPort(4).addParameter("name", "invoker4"));
|
||||||
|
|
||||||
|
given(invoker5.isAvailable()).willReturn(false);
|
||||||
|
given(invoker5.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(invoker5.getUrl()).willReturn(turl.setPort(5).addParameter("name", "invoker5"));
|
||||||
|
|
||||||
|
given(mockedInvoker1.isAvailable()).willReturn(false);
|
||||||
|
given(mockedInvoker1.getInterface()).willReturn(IHelloService.class);
|
||||||
|
given(mockedInvoker1.getUrl()).willReturn(turl.setPort(999).setProtocol("mock"));
|
||||||
|
|
||||||
|
invokers.add(invoker1);
|
||||||
|
dic = new StaticDirectory<IHelloService>(url, invokers, null);
|
||||||
|
cluster = new AbstractClusterInvoker(dic) {
|
||||||
|
@Override
|
||||||
|
protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance)
|
||||||
|
throws RpcException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cluster_nocheck =
|
||||||
|
new AbstractClusterInvoker(
|
||||||
|
dic, url.addParameterIfAbsent(CLUSTER_AVAILABLE_CHECK_KEY, Boolean.FALSE.toString())) {
|
||||||
|
@Override
|
||||||
|
protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance)
|
||||||
|
throws RpcException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initlistsize5() {
|
||||||
|
invokers.clear();
|
||||||
|
selectedInvokers
|
||||||
|
.clear(); // Clear first, previous test case will make sure that the right invoker2 will be used.
|
||||||
|
invokers.add(invoker1);
|
||||||
|
invokers.add(invoker2);
|
||||||
|
invokers.add(invoker3);
|
||||||
|
invokers.add(invoker4);
|
||||||
|
invokers.add(invoker5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDic() {
|
||||||
|
dic.notify(invokers);
|
||||||
|
dic.buildRouterChain();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test mock invoker selector works as expected
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testMockedInvokerSelect() {
|
||||||
|
initlistsize5();
|
||||||
|
invokers.add(mockedInvoker1);
|
||||||
|
|
||||||
|
initDic();
|
||||||
|
|
||||||
|
RpcInvocation mockedInvocation = new RpcInvocation();
|
||||||
|
mockedInvocation.setMethodName("sayHello");
|
||||||
|
mockedInvocation.setAttachment(INVOCATION_NEED_MOCK, "true");
|
||||||
|
List<Invoker<IHelloService>> mockedInvokers = dic.list(mockedInvocation);
|
||||||
|
Assertions.assertEquals(1, mockedInvokers.size());
|
||||||
|
|
||||||
|
List<Invoker<IHelloService>> invokers = dic.list(invocation);
|
||||||
|
Assertions.assertEquals(5, invokers.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface IHelloService {}
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.support;
|
package org.apache.dubbo.rpc.cluster.support;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
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.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
import org.apache.dubbo.rpc.support.MockInvoker;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
@ -116,7 +117,8 @@ class MockInvokerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetThrowable() {
|
void testGetThrowable() {
|
||||||
Assertions.assertThrows(RpcException.class, () -> MockInvoker.getThrowable("Exception.class"));
|
Assertions.assertThrows(
|
||||||
|
RpcException.class, () -> org.apache.dubbo.rpc.support.MockInvoker.getThrowable("Exception.class"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -62,7 +62,7 @@ class MockProviderRpcExceptionTest {
|
||||||
.addParameter("invoke_return_error", "true")
|
.addParameter("invoke_return_error", "true")
|
||||||
.addParameter(
|
.addParameter(
|
||||||
REFER_KEY,
|
REFER_KEY,
|
||||||
URL.encode(PATH_KEY + "=" + MockProviderRpcExceptionTest.IHelloRpcService.class.getName()
|
URL.encode(PATH_KEY + "=" + IHelloRpcService.class.getName()
|
||||||
+ "&" + "mock=true"
|
+ "&" + "mock=true"
|
||||||
+ "&" + "proxy=jdk"));
|
+ "&" + "proxy=jdk"));
|
||||||
Invoker<IHelloRpcService> cluster = getClusterInvoker(url);
|
Invoker<IHelloRpcService> cluster = getClusterInvoker(url);
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
|
||||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
|
|
||||||
<appender name="DUBBO" class="org.apache.dubbo.common.utils.DubboAppender">
|
|
||||||
<param name="File" value="../dubbo.log"/>
|
|
||||||
<layout class="org.apache.log4j.PatternLayout">
|
|
||||||
<param name="ConversionPattern" value="[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n"/>
|
|
||||||
</layout>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
|
|
||||||
<layout class="org.apache.log4j.PatternLayout">
|
|
||||||
<param name="ConversionPattern" value="[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n"/>
|
|
||||||
</layout>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<level value="INFO"/>
|
|
||||||
<appender-ref ref="DUBBO"/>
|
|
||||||
<appender-ref ref="CONSOLE"/>
|
|
||||||
</root>
|
|
||||||
</log4j:configuration>
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<Configuration status="WARN">
|
||||||
|
<Appenders>
|
||||||
|
<Dubbo name="Dubbo" fileName="../dubbo.log">
|
||||||
|
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] %5p %t %c{2}: %m%n%ex" charset="UTF-8"/>
|
||||||
|
</Dubbo>
|
||||||
|
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||||
|
<PatternLayout pattern="%d{HH:mm:ss.SSS} |-%highlight{%-5p} [%t] %40.40c:%-3L -| %m%n%rEx{filters(jdk.internal.reflect,java.lang.reflect,sun.reflect,org.junit,org.mockito)}" charset="UTF-8"/>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Root level="info">
|
||||||
|
<AppenderRef ref="Dubbo"/>
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
||||||
|
|
@ -99,6 +99,17 @@
|
||||||
<groupId>javax.annotation</groupId>
|
<groupId>javax.annotation</groupId>
|
||||||
<artifactId>javax.annotation-api</artifactId>
|
<artifactId>javax.annotation-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cglib</groupId>
|
||||||
|
<artifactId>cglib-nodep</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-slf4j-impl</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.protobuf</groupId>
|
<groupId>com.google.protobuf</groupId>
|
||||||
<artifactId>protobuf-java</artifactId>
|
<artifactId>protobuf-java</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
import org.apache.dubbo.common.config.ConfigurationCache;
|
import org.apache.dubbo.common.config.ConfigurationCache;
|
||||||
import org.apache.dubbo.common.convert.ConverterUtil;
|
import org.apache.dubbo.common.convert.ConverterUtil;
|
||||||
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
|
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
|
||||||
|
import org.apache.dubbo.common.serialization.ClassHolder;
|
||||||
import org.apache.dubbo.common.ssl.CertManager;
|
import org.apache.dubbo.common.ssl.CertManager;
|
||||||
import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
|
import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
|
||||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||||
|
|
@ -40,6 +41,7 @@ public class CommonScopeModelInitializer implements ScopeModelInitializer {
|
||||||
beanFactory.registerBean(SerializeSecurityManager.class);
|
beanFactory.registerBean(SerializeSecurityManager.class);
|
||||||
beanFactory.registerBean(DefaultSerializeClassChecker.class);
|
beanFactory.registerBean(DefaultSerializeClassChecker.class);
|
||||||
beanFactory.registerBean(CertManager.class);
|
beanFactory.registerBean(CertManager.class);
|
||||||
|
beanFactory.registerBean(ClassHolder.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -14,38 +14,24 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.protocol.rest.pair;
|
package org.apache.dubbo.common.aot;
|
||||||
|
|
||||||
import org.apache.dubbo.metadata.rest.media.MediaType;
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
|
|
||||||
/**
|
import static org.apache.dubbo.common.constants.CommonConstants.ThirdPartyProperty.GRAALVM_NATIVEIMAGE_IMAGECODE;
|
||||||
* for http message codec result
|
|
||||||
*/
|
public abstract class NativeDetector {
|
||||||
public class MessageCodecResultPair {
|
|
||||||
/**
|
|
||||||
* has coded
|
|
||||||
*/
|
|
||||||
boolean coded;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* codec type
|
* See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java
|
||||||
*/
|
*/
|
||||||
MediaType mediaType;
|
private static final boolean IMAGE_CODE =
|
||||||
|
(SystemPropertyConfigUtils.getSystemProperty(GRAALVM_NATIVEIMAGE_IMAGECODE) != null);
|
||||||
|
|
||||||
public MessageCodecResultPair(boolean coded, MediaType mediaType) {
|
/**
|
||||||
this.coded = coded;
|
* Returns {@code true} if invoked in the context of image building or during image runtime, else {@code false}.
|
||||||
this.mediaType = mediaType;
|
*/
|
||||||
}
|
public static boolean inNativeImage() {
|
||||||
|
return IMAGE_CODE;
|
||||||
public boolean isCoded() {
|
|
||||||
return coded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaType getMediaType() {
|
|
||||||
return mediaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MessageCodecResultPair pair(boolean coded, MediaType mediaType) {
|
|
||||||
return new MessageCodecResultPair(coded, mediaType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,14 +162,6 @@ public class FileCacheStore {
|
||||||
FileCacheStoreFactory.removeCache(cacheFilePath);
|
FileCacheStoreFactory.removeCache(cacheFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* for unit test only
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
protected String getCacheFilePath() {
|
|
||||||
return cacheFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder newBuilder() {
|
public static Builder newBuilder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.common.cache;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -30,11 +31,11 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.SystemProperty.USER_HOME;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CACHE_PATH_INACCESSIBLE;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CACHE_PATH_INACCESSIBLE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -82,7 +83,7 @@ public final class FileCacheStoreFactory {
|
||||||
public static FileCacheStore getInstance(String basePath, String cacheName, boolean enableFileCache) {
|
public static FileCacheStore getInstance(String basePath, String cacheName, boolean enableFileCache) {
|
||||||
if (basePath == null) {
|
if (basePath == null) {
|
||||||
// default case: ~/.dubbo
|
// default case: ~/.dubbo
|
||||||
basePath = System.getProperty("user.home") + File.separator + ".dubbo";
|
basePath = SystemPropertyConfigUtils.getSystemProperty(USER_HOME) + File.separator + ".dubbo";
|
||||||
}
|
}
|
||||||
if (basePath.endsWith(File.separator)) {
|
if (basePath.endsWith(File.separator)) {
|
||||||
basePath = basePath.substring(0, basePath.length() - 1);
|
basePath = basePath.substring(0, basePath.length() - 1);
|
||||||
|
|
@ -207,14 +208,6 @@ public final class FileCacheStoreFactory {
|
||||||
cacheMap.remove(cacheFileName);
|
cacheMap.remove(cacheFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* for unit test only
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
static Map<String, FileCacheStore> getCacheMap() {
|
|
||||||
return cacheMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PathNotExclusiveException extends Exception {
|
private static class PathNotExclusiveException extends Exception {
|
||||||
public PathNotExclusiveException(String msg) {
|
public PathNotExclusiveException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.common.compact;
|
||||||
|
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
|
|
@ -38,17 +39,18 @@ public class Dubbo2CompactUtils {
|
||||||
|
|
||||||
private static void initEnabled() {
|
private static void initEnabled() {
|
||||||
try {
|
try {
|
||||||
String fromProp = System.getProperty(CommonConstants.DUBBO2_COMPACT_ENABLE);
|
String fromProp =
|
||||||
|
SystemPropertyConfigUtils.getSystemProperty(CommonConstants.DubboProperty.DUBBO2_COMPACT_ENABLE);
|
||||||
if (StringUtils.isNotEmpty(fromProp)) {
|
if (StringUtils.isNotEmpty(fromProp)) {
|
||||||
enabled = Boolean.parseBoolean(fromProp);
|
enabled = Boolean.parseBoolean(fromProp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String fromEnv = System.getenv(CommonConstants.DUBBO2_COMPACT_ENABLE);
|
String fromEnv = System.getenv(CommonConstants.DubboProperty.DUBBO2_COMPACT_ENABLE);
|
||||||
if (StringUtils.isNotEmpty(fromEnv)) {
|
if (StringUtils.isNotEmpty(fromEnv)) {
|
||||||
enabled = Boolean.parseBoolean(fromEnv);
|
enabled = Boolean.parseBoolean(fromEnv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fromEnv = System.getenv(StringUtils.toOSStyleKey(CommonConstants.DUBBO2_COMPACT_ENABLE));
|
fromEnv = System.getenv(StringUtils.toOSStyleKey(CommonConstants.DubboProperty.DUBBO2_COMPACT_ENABLE));
|
||||||
enabled = !StringUtils.isNotEmpty(fromEnv) || Boolean.parseBoolean(fromEnv);
|
enabled = !StringUtils.isNotEmpty(fromEnv) || Boolean.parseBoolean(fromEnv);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,8 @@ public final class ConfigurationUtils {
|
||||||
for (Map.Entry<String, V> entry : copy.entrySet()) {
|
for (Map.Entry<String, V> entry : copy.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
V val = entry.getValue();
|
V val = entry.getValue();
|
||||||
if (StringUtils.startsWithIgnoreCase(key, prefix)
|
if ((StringUtils.startsWithIgnoreCase(key, prefix)
|
||||||
|
|| StringUtils.startsWithIgnoreCase(key, StringUtils.toOSStyleKey(prefix)))
|
||||||
&& key.length() > prefix.length()
|
&& key.length() > prefix.length()
|
||||||
&& !ConfigurationUtils.isEmptyValue(val)) {
|
&& !ConfigurationUtils.isEmptyValue(val)) {
|
||||||
|
|
||||||
|
|
@ -326,7 +327,8 @@ public final class ConfigurationUtils {
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, V> entry : copy.entrySet()) {
|
for (Map.Entry<String, V> entry : copy.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
if (StringUtils.startsWithIgnoreCase(key, prefix)
|
if ((StringUtils.startsWithIgnoreCase(key, prefix)
|
||||||
|
|| StringUtils.startsWithIgnoreCase(key, StringUtils.toOSStyleKey(prefix)))
|
||||||
&& key.length() > prefix.length()
|
&& key.length() > prefix.length()
|
||||||
&& !ConfigurationUtils.isEmptyValue(entry.getValue())) {
|
&& !ConfigurationUtils.isEmptyValue(entry.getValue())) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.ConfigUtils;
|
import org.apache.dubbo.common.utils.ConfigUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
import org.apache.dubbo.config.AbstractConfig;
|
import org.apache.dubbo.config.AbstractConfig;
|
||||||
import org.apache.dubbo.config.context.ConfigConfigurationAdapter;
|
import org.apache.dubbo.config.context.ConfigConfigurationAdapter;
|
||||||
import org.apache.dubbo.rpc.model.ScopeModel;
|
import org.apache.dubbo.rpc.model.ScopeModel;
|
||||||
|
|
@ -96,10 +97,12 @@ public class Environment extends LifecycleAdapter implements ApplicationExt {
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private void loadMigrationRule() {
|
private void loadMigrationRule() {
|
||||||
if (Boolean.parseBoolean(System.getProperty(CommonConstants.DUBBO_MIGRATION_FILE_ENABLE, "false"))) {
|
if (Boolean.parseBoolean(SystemPropertyConfigUtils.getSystemProperty(
|
||||||
String path = System.getProperty(CommonConstants.DUBBO_MIGRATION_KEY);
|
CommonConstants.DubboProperty.DUBBO_MIGRATION_FILE_ENABLE, "false"))) {
|
||||||
|
String path =
|
||||||
|
SystemPropertyConfigUtils.getSystemProperty(CommonConstants.DubboProperty.DUBBO_MIGRATION_KEY);
|
||||||
if (StringUtils.isEmpty(path)) {
|
if (StringUtils.isEmpty(path)) {
|
||||||
path = System.getenv(CommonConstants.DUBBO_MIGRATION_KEY);
|
path = System.getenv(CommonConstants.DubboProperty.DUBBO_MIGRATION_KEY);
|
||||||
if (StringUtils.isEmpty(path)) {
|
if (StringUtils.isEmpty(path)) {
|
||||||
path = CommonConstants.DEFAULT_DUBBO_MIGRATION_FILE;
|
path = CommonConstants.DEFAULT_DUBBO_MIGRATION_FILE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.dubbo.common.config.configcenter;
|
package org.apache.dubbo.common.config.configcenter;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration;
|
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -30,7 +29,7 @@ import static org.apache.dubbo.common.utils.PathUtils.normalize;
|
||||||
/**
|
/**
|
||||||
* An abstract implementation of {@link DynamicConfiguration} is like "tree-structure" path :
|
* An abstract implementation of {@link DynamicConfiguration} is like "tree-structure" path :
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link FileSystemDynamicConfiguration "file"}</li>
|
* <li>{@link org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration "file"}</li>
|
||||||
* <li>{@link org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration "zookeeper"}</li>
|
* <li>{@link org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration "zookeeper"}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String DISABLED_KEY = "disabled";
|
String DISABLED_KEY = "disabled";
|
||||||
|
|
||||||
String DUBBO_PROPERTIES_KEY = "dubbo.properties.file";
|
|
||||||
|
|
||||||
String DEFAULT_DUBBO_PROPERTIES = "dubbo.properties";
|
String DEFAULT_DUBBO_PROPERTIES = "dubbo.properties";
|
||||||
|
|
||||||
String DUBBO_MIGRATION_KEY = "dubbo.migration.file";
|
|
||||||
|
|
||||||
String DUBBO_MIGRATION_FILE_ENABLE = "dubbo.migration-file.enable";
|
|
||||||
|
|
||||||
String DEFAULT_DUBBO_MIGRATION_FILE = "dubbo-migration.yaml";
|
String DEFAULT_DUBBO_MIGRATION_FILE = "dubbo-migration.yaml";
|
||||||
|
|
||||||
String ANY_VALUE = "*";
|
String ANY_VALUE = "*";
|
||||||
|
|
@ -128,6 +122,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String THREAD_POOL_EXHAUSTED_LISTENERS_KEY = "thread-pool-exhausted-listeners";
|
String THREAD_POOL_EXHAUSTED_LISTENERS_KEY = "thread-pool-exhausted-listeners";
|
||||||
|
|
||||||
|
String JSON_CHECK_LEVEL_KEY = "jsonCheckLevel";
|
||||||
|
|
||||||
String THREADS_KEY = "threads";
|
String THREADS_KEY = "threads";
|
||||||
|
|
||||||
String QUEUES_KEY = "queues";
|
String QUEUES_KEY = "queues";
|
||||||
|
|
@ -291,6 +287,8 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String CLUSTER_KEY = "cluster";
|
String CLUSTER_KEY = "cluster";
|
||||||
|
|
||||||
|
String MERGEABLE_CLUSTER_NAME = "mergeable";
|
||||||
|
|
||||||
String USERNAME_KEY = "username";
|
String USERNAME_KEY = "username";
|
||||||
|
|
||||||
String PASSWORD_KEY = "password";
|
String PASSWORD_KEY = "password";
|
||||||
|
|
@ -306,14 +304,6 @@ public interface CommonConstants {
|
||||||
*/
|
*/
|
||||||
String BROADCAST_CLUSTER = "broadcast";
|
String BROADCAST_CLUSTER = "broadcast";
|
||||||
|
|
||||||
/**
|
|
||||||
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
|
|
||||||
* the Dubbo application prefers
|
|
||||||
*
|
|
||||||
* @since 2.7.6
|
|
||||||
*/
|
|
||||||
String DUBBO_PREFERRED_NETWORK_INTERFACE = "dubbo.network.interface.preferred";
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
String SHUTDOWN_WAIT_SECONDS_KEY = "dubbo.service.shutdown.wait.seconds";
|
String SHUTDOWN_WAIT_SECONDS_KEY = "dubbo.service.shutdown.wait.seconds";
|
||||||
|
|
||||||
|
|
@ -454,12 +444,6 @@ public interface CommonConstants {
|
||||||
*/
|
*/
|
||||||
String DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH = "META-INF/dubbo/service-name-mapping.properties";
|
String DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH = "META-INF/dubbo/service-name-mapping.properties";
|
||||||
|
|
||||||
String CLASS_DESERIALIZE_BLOCK_ALL = "dubbo.security.serialize.blockAllClassExceptAllow";
|
|
||||||
|
|
||||||
String CLASS_DESERIALIZE_ALLOWED_LIST = "dubbo.security.serialize.allowedClassList";
|
|
||||||
|
|
||||||
String CLASS_DESERIALIZE_BLOCKED_LIST = "dubbo.security.serialize.blockedClassList";
|
|
||||||
|
|
||||||
String ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE = "dubbo.security.serialize.generic.native-java-enable";
|
String ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE = "dubbo.security.serialize.generic.native-java-enable";
|
||||||
|
|
||||||
String SERIALIZE_BLOCKED_LIST_FILE_PATH = "security/serialize.blockedlist";
|
String SERIALIZE_BLOCKED_LIST_FILE_PATH = "security/serialize.blockedlist";
|
||||||
|
|
@ -491,8 +475,6 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String DEFAULT_VERSION = "0.0.0";
|
String DEFAULT_VERSION = "0.0.0";
|
||||||
|
|
||||||
String CLASS_DESERIALIZE_OPEN_CHECK = "dubbo.security.serialize.openCheckClass";
|
|
||||||
|
|
||||||
String ROUTER_KEY = "router";
|
String ROUTER_KEY = "router";
|
||||||
|
|
||||||
String EXPORT_ASYNC_KEY = "export-async";
|
String EXPORT_ASYNC_KEY = "export-async";
|
||||||
|
|
@ -520,11 +502,6 @@ public interface CommonConstants {
|
||||||
*/
|
*/
|
||||||
String URL_MERGE_PROCESSOR_KEY = "url-merge-processor";
|
String URL_MERGE_PROCESSOR_KEY = "url-merge-processor";
|
||||||
|
|
||||||
/**
|
|
||||||
* use native image to compile dubbo's identifier
|
|
||||||
*/
|
|
||||||
String NATIVE = "native";
|
|
||||||
|
|
||||||
String DUBBO_MONITOR_ADDRESS = "dubbo.monitor.address";
|
String DUBBO_MONITOR_ADDRESS = "dubbo.monitor.address";
|
||||||
|
|
||||||
String SERVICE_NAME_MAPPING_KEY = "service-name-mapping";
|
String SERVICE_NAME_MAPPING_KEY = "service-name-mapping";
|
||||||
|
|
@ -533,16 +510,6 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String SERVICE_MODEL = "serviceModel";
|
String SERVICE_MODEL = "serviceModel";
|
||||||
|
|
||||||
/**
|
|
||||||
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
|
|
||||||
* the Dubbo application will be ignored
|
|
||||||
*
|
|
||||||
* @since 2.7.6
|
|
||||||
*/
|
|
||||||
String DUBBO_NETWORK_IGNORED_INTERFACE = "dubbo.network.interface.ignored";
|
|
||||||
|
|
||||||
String OS_NAME_KEY = "os.name";
|
|
||||||
|
|
||||||
String OS_LINUX_PREFIX = "linux";
|
String OS_LINUX_PREFIX = "linux";
|
||||||
|
|
||||||
String OS_WIN_PREFIX = "win";
|
String OS_WIN_PREFIX = "win";
|
||||||
|
|
@ -587,10 +554,6 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String INJVM_IGNORE_SAME_MODULE_KEY = "injvm.ignore.same-module";
|
String INJVM_IGNORE_SAME_MODULE_KEY = "injvm.ignore.same-module";
|
||||||
|
|
||||||
String SET_FUTURE_IN_SYNC_MODE = "future.sync.set";
|
|
||||||
|
|
||||||
String CLEAR_FUTURE_AFTER_GET = "future.clear.once";
|
|
||||||
|
|
||||||
String NATIVE_STUB = "nativestub";
|
String NATIVE_STUB = "nativestub";
|
||||||
|
|
||||||
String METADATA = "metadata";
|
String METADATA = "metadata";
|
||||||
|
|
@ -599,8 +562,6 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String OPTIMIZER_KEY = "optimizer";
|
String OPTIMIZER_KEY = "optimizer";
|
||||||
|
|
||||||
String PREFER_JSON_FRAMEWORK_NAME = "dubbo.json-framework.prefer";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -648,11 +609,6 @@ public interface CommonConstants {
|
||||||
|
|
||||||
boolean DEFAULT_ENCODE_IN_IO_THREAD = false;
|
boolean DEFAULT_ENCODE_IN_IO_THREAD = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
String BYTE_ACCESSOR_KEY = "byte.accessor";
|
|
||||||
|
|
||||||
String PAYLOAD = "payload";
|
String PAYLOAD = "payload";
|
||||||
|
|
||||||
String DUBBO_METRICS_CONFIGCENTER_ENABLE = "dubbo.metrics.configcenter.enable";
|
String DUBBO_METRICS_CONFIGCENTER_ENABLE = "dubbo.metrics.configcenter.enable";
|
||||||
|
|
@ -663,11 +619,165 @@ public interface CommonConstants {
|
||||||
|
|
||||||
String DUBBO_PACKABLE_METHOD_FACTORY = "dubbo.application.parameters." + PACKABLE_METHOD_FACTORY_KEY;
|
String DUBBO_PACKABLE_METHOD_FACTORY = "dubbo.application.parameters." + PACKABLE_METHOD_FACTORY_KEY;
|
||||||
|
|
||||||
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
|
String DUBBO_TAG_HEADER = "dubbo-tag";
|
||||||
|
|
||||||
String DUBBO2_COMPACT_ENABLE = "dubbo.compact.enable";
|
String REST_SERVICE_DEPLOYER_URL_ATTRIBUTE_KEY = "restServiceDeployerAttributeKey";
|
||||||
|
|
||||||
|
String POD_NAMESPACE = "POD_NAMESPACE";
|
||||||
|
|
||||||
|
String CLUSTER_DOMAIN = "CLUSTER_DOMAIN";
|
||||||
|
|
||||||
|
String EXT_PROTOCOL = "ext.protocol";
|
||||||
|
|
||||||
|
String IS_EXTRA = "isExtra";
|
||||||
|
|
||||||
String ZOOKEEPER_ENSEMBLE_TRACKER_KEY = "zookeeper.ensemble.tracker";
|
String ZOOKEEPER_ENSEMBLE_TRACKER_KEY = "zookeeper.ensemble.tracker";
|
||||||
|
|
||||||
String DUBBO_VERSIONS_KEY = "META-INF/dubbo-versions";
|
String DUBBO_VERSIONS_KEY = "META-INF/dubbo-versions";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System-related VM properties
|
||||||
|
*/
|
||||||
|
interface SystemProperty {
|
||||||
|
|
||||||
|
String USER_HOME = "user.home";
|
||||||
|
|
||||||
|
String SYSTEM_JAVA_VERSION = "java.version";
|
||||||
|
|
||||||
|
String SYSTEM_JAVA_IO_TMPDIR = "java.io.tmpdir";
|
||||||
|
|
||||||
|
String SYSTEM_LINE_SEPARATOR = "line.separator";
|
||||||
|
|
||||||
|
String SERIALIZATION_SECURITY_CHECK_KEY = "serialization.security.check";
|
||||||
|
|
||||||
|
String SYSTEM_BYTE_ACCESSOR_KEY = "byte.accessor";
|
||||||
|
|
||||||
|
String SYSTEM_OS_NAME = "os.name";
|
||||||
|
|
||||||
|
String SYSTEM_OS_VERSION = "os.version";
|
||||||
|
|
||||||
|
String JAVA_RUNTIME_NAME = "java.runtime.name";
|
||||||
|
|
||||||
|
String JAVA_RUNTIME_VERSION = "java.runtime.version";
|
||||||
|
|
||||||
|
String JAVA_VM_NAME = "java.vm.name";
|
||||||
|
|
||||||
|
String JAVA_VM_VERSION = "java.vm.version";
|
||||||
|
|
||||||
|
String JAVA_VM_INFO = "java.vm.info";
|
||||||
|
|
||||||
|
String JAVA_HOME = "java.home";
|
||||||
|
|
||||||
|
String OS_ARCH = "os.arch";
|
||||||
|
|
||||||
|
String SYSTEM_FILE_ENCODING = "file.encoding";
|
||||||
|
|
||||||
|
String SYSTEM_TCP_RESPONSE_TIMEOUT = "sun.rmi.transport.tcp.responseTimeout";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Third-party-related VM properties
|
||||||
|
*/
|
||||||
|
interface ThirdPartyProperty {
|
||||||
|
String NETTY_EPOLL_ENABLE_KEY = "netty.epoll.enable";
|
||||||
|
|
||||||
|
String SET_FUTURE_IN_SYNC_MODE = "future.sync.set";
|
||||||
|
|
||||||
|
String CLEAR_FUTURE_AFTER_GET = "future.clear.once";
|
||||||
|
|
||||||
|
String APOLLO_ADDR_KEY = "apollo.meta";
|
||||||
|
|
||||||
|
String APOLLO_CLUSTER_KEY = "apollo.cluster";
|
||||||
|
|
||||||
|
String APOLLO_ENV_KEY = "env";
|
||||||
|
|
||||||
|
String APOLLO_APPID_KEY = "app.id";
|
||||||
|
|
||||||
|
String NACOS_SERVICE_NAME_SEPARATOR = "nacos.service.name.separator";
|
||||||
|
|
||||||
|
String GRAALVM_NATIVEIMAGE_IMAGECODE = "org.graalvm.nativeimage.imagecode";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JVM arguments to set if it can use embedded zookeeper, the default value is {@code true}.
|
||||||
|
*/
|
||||||
|
String ZOOKEEPER_CONFIG_ENABLE_EMBEDDED = "enableEmbeddedZookeeper";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo custom VM properties
|
||||||
|
*/
|
||||||
|
interface DubboProperty {
|
||||||
|
String DUBBO_MIGRATION_FILE_ENABLE = "dubbo.migration-file.enable";
|
||||||
|
String DUBBO_MIGRATION_KEY = "dubbo.migration.file";
|
||||||
|
String DUBBO_APPLICATION_LOGGER = "dubbo.application.logger";
|
||||||
|
String DUBBO_PROPERTIES_KEY = "dubbo.properties.file";
|
||||||
|
String DUBBO_PREFER_JSON_FRAMEWORK_NAME = "dubbo.json-framework.prefer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used in JVMUtil.java ,Control stack print lines, default is 32 lines
|
||||||
|
*/
|
||||||
|
String DUBBO_JSTACK_MAXLINE = "dubbo.jstack-dump.max-line";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that the Dubbo
|
||||||
|
* application will be ignored
|
||||||
|
*
|
||||||
|
* @since 2.7.6
|
||||||
|
*/
|
||||||
|
String DUBBO_NETWORK_IGNORED_INTERFACE = "dubbo.network.interface.ignored";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that the Dubbo
|
||||||
|
* application prefers
|
||||||
|
*
|
||||||
|
* @since 2.7.6
|
||||||
|
*/
|
||||||
|
String DUBBO_PREFERRED_NETWORK_INTERFACE = "dubbo.network.interface.preferred";
|
||||||
|
|
||||||
|
String DUBBO_CLASS_DESERIALIZE_ALLOWED_LIST = "dubbo.security.serialize.allowedClassList";
|
||||||
|
String DUBBO_CLASS_DESERIALIZE_BLOCKED_LIST = "dubbo.security.serialize.blockedClassList";
|
||||||
|
String DUBBO_CLASS_DESERIALIZE_OPEN_CHECK = "dubbo.security.serialize.openCheckClass";
|
||||||
|
String DUBBO_CLASS_DESERIALIZE_BLOCK_ALL = "dubbo.security.serialize.blockAllClassExceptAllow";
|
||||||
|
String DUBBO_RESOLVE_FILE = "dubbo.resolve.file";
|
||||||
|
String DUBBO_IP_TO_REGISTRY = "DUBBO_IP_TO_REGISTRY";
|
||||||
|
String DUBBO_MONITOR_ADDRESS = "dubbo.monitor.address";
|
||||||
|
String DUBBO_CONTAINER_KEY = "dubbo.container";
|
||||||
|
String DUBBO_SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";
|
||||||
|
String DUBBO_SPRING_CONFIG = "dubbo.spring.config";
|
||||||
|
String DUBBO_MAPPING_CACHE_FILEPATH = "dubbo.mapping.cache.filePath";
|
||||||
|
|
||||||
|
String DUBBO_MAPPING_CACHE_FILENAME = "dubbo.mapping.cache.fileName";
|
||||||
|
|
||||||
|
String DUBBO_MAPPING_CACHE_ENTRYSIZE = "dubbo.mapping.cache.entrySize";
|
||||||
|
|
||||||
|
String DUBBO_MAPPING_CACHE_MAXFILESIZE = "dubbo.mapping.cache.maxFileSize";
|
||||||
|
|
||||||
|
String DUBBO_META_CACHE_FILEPATH = "dubbo.meta.cache.filePath";
|
||||||
|
|
||||||
|
String DUBBO_META_CACHE_FILENAME = "dubbo.meta.cache.fileName";
|
||||||
|
|
||||||
|
String DUBBO_META_CACHE_ENTRYSIZE = "dubbo.meta.cache.entrySize";
|
||||||
|
|
||||||
|
String DUBBO_META_CACHE_MAXFILESIZE = "dubbo.meta.cache.maxFileSize";
|
||||||
|
|
||||||
|
String DUBBO_USE_SECURE_RANDOM_ID = "dubbo.application.use-secure-random-request-id";
|
||||||
|
|
||||||
|
String DUBBO_CLOSE_TIMEOUT_CONFIG_KEY = "dubbo.protocol.default-close-timeout";
|
||||||
|
|
||||||
|
String DUBBO_HEARTBEAT_CONFIG_KEY = "dubbo.protocol.default-heartbeat";
|
||||||
|
|
||||||
|
String DUBBO_DEFAULT_REMOTING_SERIALIZATION_PROPERTY = "DUBBO_DEFAULT_SERIALIZATION";
|
||||||
|
|
||||||
|
String DUBBO_HESSIAN_ALLOW_NON_SERIALIZABLE = "dubbo.hessian.allowNonSerializable";
|
||||||
|
|
||||||
|
String DUBBO_HESSIAN_WHITELIST = "dubbo.application.hessian2.whitelist";
|
||||||
|
|
||||||
|
String DUBBO_HESSIAN_ALLOW = "dubbo.application.hessian2.allow";
|
||||||
|
|
||||||
|
String DUBBO_HESSIAN_DENY = "dubbo.application.hessian2.deny";
|
||||||
|
|
||||||
|
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
|
||||||
|
|
||||||
|
String DUBBO2_COMPACT_ENABLE = "dubbo.compact.enable";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ public interface LoggerCodeConstants {
|
||||||
|
|
||||||
String VULNERABILITY_WARNING = "0-28";
|
String VULNERABILITY_WARNING = "0-28";
|
||||||
|
|
||||||
|
String COMMON_NOT_FOUND_TRACER_DEPENDENCY = "0-29";
|
||||||
|
|
||||||
// Registry module
|
// Registry module
|
||||||
|
|
||||||
String REGISTRY_ADDRESS_INVALID = "1-1";
|
String REGISTRY_ADDRESS_INVALID = "1-1";
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ public interface MetricsConstants {
|
||||||
|
|
||||||
String TAG_CHANGE_TYPE = "change.type";
|
String TAG_CHANGE_TYPE = "change.type";
|
||||||
|
|
||||||
|
String TAG_ERROR_CODE = "error";
|
||||||
|
|
||||||
String ENABLE_JVM_METRICS_KEY = "enable.jvm";
|
String ENABLE_JVM_METRICS_KEY = "enable.jvm";
|
||||||
|
|
||||||
String ENABLE_COLLECTOR_SYNC_KEY = "enable.collector.sync";
|
String ENABLE_COLLECTOR_SYNC_KEY = "enable.collector.sync";
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ public interface RegistryConstants {
|
||||||
String ENABLE_EMPTY_PROTECTION_KEY = "enable-empty-protection";
|
String ENABLE_EMPTY_PROTECTION_KEY = "enable-empty-protection";
|
||||||
boolean DEFAULT_ENABLE_EMPTY_PROTECTION = false;
|
boolean DEFAULT_ENABLE_EMPTY_PROTECTION = false;
|
||||||
String REGISTER_CONSUMER_URL_KEY = "register-consumer-url";
|
String REGISTER_CONSUMER_URL_KEY = "register-consumer-url";
|
||||||
|
String REGISTRY_PROTOCOL_TYPE = "registry-protocol-type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* export noting suffix servicename
|
* export noting suffix servicename
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_MONITOR_EXCEPTION;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_MONITOR_EXCEPTION;
|
||||||
|
import static org.apache.dubbo.common.deploy.DeployState.COMPLETION;
|
||||||
import static org.apache.dubbo.common.deploy.DeployState.FAILED;
|
import static org.apache.dubbo.common.deploy.DeployState.FAILED;
|
||||||
import static org.apache.dubbo.common.deploy.DeployState.PENDING;
|
import static org.apache.dubbo.common.deploy.DeployState.PENDING;
|
||||||
import static org.apache.dubbo.common.deploy.DeployState.STARTED;
|
import static org.apache.dubbo.common.deploy.DeployState.STARTED;
|
||||||
|
|
@ -56,12 +57,17 @@ public abstract class AbstractDeployer<E extends ScopeModel> implements Deployer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return state == STARTING || state == STARTED;
|
return state == STARTING || state == STARTED || state == COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStarted() {
|
public boolean isStarted() {
|
||||||
return state == STARTED;
|
return state == STARTED || state == COMPLETION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCompletion() {
|
||||||
|
return state == COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -135,6 +141,22 @@ public abstract class AbstractDeployer<E extends ScopeModel> implements Deployer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setCompletion() {
|
||||||
|
this.state = COMPLETION;
|
||||||
|
for (DeployListener<E> listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.onCompletion(scopeModel);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error(
|
||||||
|
COMMON_MONITOR_EXCEPTION,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
getIdentifier() + " an exception occurred when handle completion event",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void setStopping() {
|
protected void setStopping() {
|
||||||
this.state = STOPPING;
|
this.state = STOPPING;
|
||||||
for (DeployListener<E> listener : listeners) {
|
for (DeployListener<E> listener : listeners) {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,9 @@ public interface ApplicationDeployer extends Deployer<ApplicationModel> {
|
||||||
/**
|
/**
|
||||||
* Register application instance and start internal services
|
* Register application instance and start internal services
|
||||||
*/
|
*/
|
||||||
void prepareApplicationInstance();
|
void prepareApplicationInstance(ModuleModel moduleModel);
|
||||||
|
|
||||||
|
void exportMetadataService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register application instance and start internal services
|
* Register application instance and start internal services
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,35 @@ public interface DeployListener<E extends ScopeModel> {
|
||||||
*/
|
*/
|
||||||
void onInitialize(E scopeModel);
|
void onInitialize(E scopeModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered before starting module.
|
||||||
|
*/
|
||||||
void onStarting(E scopeModel);
|
void onStarting(E scopeModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered before registering and exposing the service.
|
||||||
|
*/
|
||||||
void onStarted(E scopeModel);
|
void onStarted(E scopeModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered after deployer startup is complete.
|
||||||
|
*/
|
||||||
|
default void onCompletion(E scopeModel) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered before the app is destroyed,
|
||||||
|
* can do some customized things before offline the service and destroy reference.
|
||||||
|
*/
|
||||||
void onStopping(E scopeModel);
|
void onStopping(E scopeModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered after the application is destroyed,
|
||||||
|
* can do some customized things after the service is offline and the reference is destroyed.
|
||||||
|
*/
|
||||||
void onStopped(E scopeModel);
|
void onStopped(E scopeModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful to do something when deployer was failed.
|
||||||
|
*/
|
||||||
void onFailure(E scopeModel, Throwable cause);
|
void onFailure(E scopeModel, Throwable cause);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ public class DeployListenerAdapter<E extends ScopeModel> implements DeployListen
|
||||||
@Override
|
@Override
|
||||||
public void onStarted(E scopeModel) {}
|
public void onStarted(E scopeModel) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCompletion(E scopeModel) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopping(E scopeModel) {}
|
public void onStopping(E scopeModel) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@ public enum DeployState {
|
||||||
*/
|
*/
|
||||||
STARTED,
|
STARTED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completion
|
||||||
|
*/
|
||||||
|
COMPLETION,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stopping
|
* Stopping
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ public interface Deployer<E extends ScopeModel> {
|
||||||
*/
|
*/
|
||||||
boolean isStarted();
|
boolean isStarted();
|
||||||
|
|
||||||
|
boolean isCompletion();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the component is starting.
|
* @return true if the component is starting.
|
||||||
* @see #isStarted()
|
* @see #isStarted()
|
||||||
|
|
|
||||||
|
|
@ -50,4 +50,8 @@ public interface ModuleDeployer extends Deployer<ModuleModel> {
|
||||||
* Whether start in background, do not await finish
|
* Whether start in background, do not await finish
|
||||||
*/
|
*/
|
||||||
boolean isBackground();
|
boolean isBackground();
|
||||||
|
|
||||||
|
boolean hasRegistryInteraction();
|
||||||
|
|
||||||
|
ApplicationDeployer getApplicationDeployer();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ public @interface Activate {
|
||||||
/**
|
/**
|
||||||
* Absolute ordering info, optional
|
* Absolute ordering info, optional
|
||||||
*
|
*
|
||||||
* Ascending order, smaller values will be in the front o the list.
|
* Ascending order, smaller values will be in the front of the list.
|
||||||
*
|
*
|
||||||
* @return absolute ordering info
|
* @return absolute ordering info
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.extension;
|
package org.apache.dubbo.common.extension;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uniform accessor for extension
|
* Uniform accessor for extension
|
||||||
*/
|
*/
|
||||||
|
|
@ -24,7 +27,7 @@ public interface ExtensionAccessor {
|
||||||
ExtensionDirector getExtensionDirector();
|
ExtensionDirector getExtensionDirector();
|
||||||
|
|
||||||
default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
|
default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
|
||||||
return this.getExtensionDirector().getExtensionLoader(type);
|
return getExtensionDirector().getExtensionLoader(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
default <T> T getExtension(Class<T> type, String name) {
|
default <T> T getExtension(Class<T> type, String name) {
|
||||||
|
|
@ -41,4 +44,21 @@ public interface ExtensionAccessor {
|
||||||
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
|
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
|
||||||
return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
|
return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default <T> List<T> getActivateExtensions(Class<T> type) {
|
||||||
|
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
|
||||||
|
return extensionLoader != null ? extensionLoader.getActivateExtensions() : Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> T getFirstActivateExtension(Class<T> type) {
|
||||||
|
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
|
||||||
|
if (extensionLoader == null) {
|
||||||
|
throw new IllegalArgumentException("ExtensionLoader for [" + type + "] is not found");
|
||||||
|
}
|
||||||
|
List<T> extensions = extensionLoader.getActivateExtensions();
|
||||||
|
if (extensions.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("No activate extensions for [" + type + "] found");
|
||||||
|
}
|
||||||
|
return extensions.get(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.common.extension;
|
||||||
|
|
||||||
import org.apache.dubbo.common.Extension;
|
import org.apache.dubbo.common.Extension;
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.common.aot.NativeDetector;
|
||||||
import org.apache.dubbo.common.beans.support.InstantiationStrategy;
|
import org.apache.dubbo.common.beans.support.InstantiationStrategy;
|
||||||
import org.apache.dubbo.common.compact.Dubbo2ActivateUtils;
|
import org.apache.dubbo.common.compact.Dubbo2ActivateUtils;
|
||||||
import org.apache.dubbo.common.compact.Dubbo2CompactUtils;
|
import org.apache.dubbo.common.compact.Dubbo2CompactUtils;
|
||||||
|
|
@ -35,7 +36,6 @@ import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
import org.apache.dubbo.common.utils.ConfigUtils;
|
import org.apache.dubbo.common.utils.ConfigUtils;
|
||||||
import org.apache.dubbo.common.utils.Holder;
|
import org.apache.dubbo.common.utils.Holder;
|
||||||
import org.apache.dubbo.common.utils.NativeUtils;
|
|
||||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
|
@ -75,6 +75,7 @@ import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -120,6 +121,7 @@ public class ExtensionLoader<T> {
|
||||||
|
|
||||||
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
|
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final ReentrantLock loadExtensionClassesLock = new ReentrantLock();
|
||||||
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
||||||
|
|
||||||
private final Map<String, Object> cachedActivates = Collections.synchronizedMap(new LinkedHashMap<>());
|
private final Map<String, Object> cachedActivates = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||||
|
|
@ -951,7 +953,8 @@ public class ExtensionLoader<T> {
|
||||||
private Map<String, Class<?>> getExtensionClasses() {
|
private Map<String, Class<?>> getExtensionClasses() {
|
||||||
Map<String, Class<?>> classes = cachedClasses.get();
|
Map<String, Class<?>> classes = cachedClasses.get();
|
||||||
if (classes == null) {
|
if (classes == null) {
|
||||||
synchronized (cachedClasses) {
|
loadExtensionClassesLock.lock();
|
||||||
|
try {
|
||||||
classes = cachedClasses.get();
|
classes = cachedClasses.get();
|
||||||
if (classes == null) {
|
if (classes == null) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -968,6 +971,8 @@ public class ExtensionLoader<T> {
|
||||||
}
|
}
|
||||||
cachedClasses.set(classes);
|
cachedClasses.set(classes);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
loadExtensionClassesLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return classes;
|
return classes;
|
||||||
|
|
@ -1451,7 +1456,7 @@ public class ExtensionLoader<T> {
|
||||||
// Adaptive Classes' ClassLoader should be the same with Real SPI interface classes' ClassLoader
|
// Adaptive Classes' ClassLoader should be the same with Real SPI interface classes' ClassLoader
|
||||||
ClassLoader classLoader = type.getClassLoader();
|
ClassLoader classLoader = type.getClassLoader();
|
||||||
try {
|
try {
|
||||||
if (NativeUtils.isNative()) {
|
if (NativeDetector.inNativeImage()) {
|
||||||
return classLoader.loadClass(type.getName() + "$Adaptive");
|
return classLoader.loadClass(type.getName() + "$Adaptive");
|
||||||
}
|
}
|
||||||
} catch (Throwable ignore) {
|
} catch (Throwable ignore) {
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,21 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.io;
|
package org.apache.dubbo.common.io;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream utils.
|
* Stream utils.
|
||||||
*/
|
*/
|
||||||
public class StreamUtils {
|
public final class StreamUtils {
|
||||||
|
|
||||||
|
public static final ByteArrayInputStream EMPTY = new ByteArrayInputStream(new byte[0]);
|
||||||
|
|
||||||
private StreamUtils() {}
|
private StreamUtils() {}
|
||||||
|
|
||||||
public static InputStream limitedInputStream(final InputStream is, final int limit) throws IOException {
|
public static InputStream limitedInputStream(final InputStream is, final int limit) throws IOException {
|
||||||
|
|
@ -229,4 +237,51 @@ public class StreamUtils {
|
||||||
is.skip(is.available());
|
is.skip(is.available());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void copy(InputStream in, OutputStream out) throws IOException {
|
||||||
|
if (in.getClass() == ByteArrayInputStream.class) {
|
||||||
|
copy((ByteArrayInputStream) in, out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copy(ByteArrayInputStream in, OutputStream out) throws IOException {
|
||||||
|
int len = in.available();
|
||||||
|
byte[] buffer = new byte[len];
|
||||||
|
in.read(buffer, 0, len);
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] readBytes(InputStream in) throws IOException {
|
||||||
|
if (in.getClass() == ByteArrayInputStream.class) {
|
||||||
|
return readBytes((ByteArrayInputStream) in);
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] readBytes(ByteArrayInputStream in) throws IOException {
|
||||||
|
int len = in.available();
|
||||||
|
byte[] bytes = new byte[len];
|
||||||
|
in.read(bytes, 0, len);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(InputStream in) throws IOException {
|
||||||
|
return new String(readBytes(in), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(InputStream in, Charset charset) throws IOException {
|
||||||
|
return new String(readBytes(in), charset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,19 @@ public class GsonUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toJson(Object obj) throws RuntimeException {
|
||||||
|
if (!isSupportGson()) {
|
||||||
|
throw new RuntimeException("Gson is not supported. Please import Gson in JVM env.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return getGson().toJson(obj);
|
||||||
|
} catch (JsonSyntaxException ex) {
|
||||||
|
throw new RuntimeException(String.format(
|
||||||
|
"Generic serialization [%s] Json syntax exception thrown when parsing (object:%s ) error:%s",
|
||||||
|
GENERIC_SERIALIZATION_GSON, obj, ex.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Gson getGson() {
|
private static Gson getGson() {
|
||||||
if (gsonCache == null || !(gsonCache instanceof Gson)) {
|
if (gsonCache == null || !(gsonCache instanceof Gson)) {
|
||||||
synchronized (GsonUtils.class) {
|
synchronized (GsonUtils.class) {
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,14 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.json;
|
package org.apache.dubbo.common.json;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.extension.SPI;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface JSON {
|
@SPI
|
||||||
|
public interface JsonUtil {
|
||||||
boolean isSupport();
|
boolean isSupport();
|
||||||
|
|
||||||
boolean isJson(String json);
|
boolean isJson(String json);
|
||||||
|
|
@ -39,6 +42,10 @@ public interface JSON {
|
||||||
|
|
||||||
Map<String, ?> getObject(Map<String, ?> obj, String key);
|
Map<String, ?> getObject(Map<String, ?> obj, String key);
|
||||||
|
|
||||||
|
Object convertObject(Object obj, Type type);
|
||||||
|
|
||||||
|
Object convertObject(Object obj, Class<?> clazz);
|
||||||
|
|
||||||
Double getNumberAsDouble(Map<String, ?> obj, String key);
|
Double getNumberAsDouble(Map<String, ?> obj, String key);
|
||||||
|
|
||||||
Integer getNumberAsInteger(Map<String, ?> obj, String key);
|
Integer getNumberAsInteger(Map<String, ?> obj, String key);
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.json.impl;
|
package org.apache.dubbo.common.json.impl;
|
||||||
|
|
||||||
import org.apache.dubbo.common.json.JSON;
|
import org.apache.dubbo.common.json.JsonUtil;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -24,7 +24,7 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class AbstractJSONImpl implements JSON {
|
public abstract class AbstractJsonUtilImpl implements JsonUtil {
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupport() {
|
public boolean isSupport() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -22,7 +22,7 @@ import java.util.List;
|
||||||
import com.alibaba.fastjson2.JSONValidator;
|
import com.alibaba.fastjson2.JSONValidator;
|
||||||
import com.alibaba.fastjson2.JSONWriter;
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
|
|
||||||
public class FastJson2Impl extends AbstractJSONImpl {
|
public class FastJson2Impl extends AbstractJsonUtilImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isJson(String json) {
|
public boolean isJson(String json) {
|
||||||
|
|
@ -44,4 +44,14 @@ public class FastJson2Impl extends AbstractJSONImpl {
|
||||||
public String toJson(Object obj) {
|
public String toJson(Object obj) {
|
||||||
return com.alibaba.fastjson2.JSON.toJSONString(obj, JSONWriter.Feature.WriteEnumsUsingName);
|
return com.alibaba.fastjson2.JSON.toJSONString(obj, JSONWriter.Feature.WriteEnumsUsingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Type type) {
|
||||||
|
return com.alibaba.fastjson2.util.TypeUtils.cast(obj, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Class<?> clazz) {
|
||||||
|
return com.alibaba.fastjson2.util.TypeUtils.cast(obj, clazz);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ package org.apache.dubbo.common.json.impl;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.parser.ParserConfig;
|
||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
|
||||||
public class FastJsonImpl extends AbstractJSONImpl {
|
public class FastJsonImpl extends AbstractJsonUtilImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isJson(String json) {
|
public boolean isJson(String json) {
|
||||||
|
|
@ -47,4 +48,14 @@ public class FastJsonImpl extends AbstractJSONImpl {
|
||||||
public String toJson(Object obj) {
|
public String toJson(Object obj) {
|
||||||
return com.alibaba.fastjson.JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
|
return com.alibaba.fastjson.JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Type type) {
|
||||||
|
return com.alibaba.fastjson.util.TypeUtils.cast(obj, type, ParserConfig.getGlobalInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Class<?> clazz) {
|
||||||
|
return com.alibaba.fastjson.util.TypeUtils.cast(obj, clazz, ParserConfig.getGlobalInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
public class GsonImpl extends AbstractJSONImpl {
|
public class GsonImpl extends AbstractJsonUtilImpl {
|
||||||
// weak reference of com.google.gson.Gson, prevent throw exception when init
|
// weak reference of com.google.gson.Gson, prevent throw exception when init
|
||||||
private volatile Object gsonCache = null;
|
private volatile Object gsonCache = null;
|
||||||
|
|
||||||
|
|
@ -55,6 +55,18 @@ public class GsonImpl extends AbstractJSONImpl {
|
||||||
return getGson().toJson(obj);
|
return getGson().toJson(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Type type) {
|
||||||
|
Gson gson = getGson();
|
||||||
|
return gson.fromJson(gson.toJsonTree(obj), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Class<?> clazz) {
|
||||||
|
Gson gson = getGson();
|
||||||
|
return gson.fromJson(gson.toJsonTree(obj), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
private Gson getGson() {
|
private Gson getGson() {
|
||||||
if (gsonCache == null || !(gsonCache instanceof Gson)) {
|
if (gsonCache == null || !(gsonCache instanceof Gson)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
|
||||||
public class JacksonImpl extends AbstractJSONImpl {
|
public class JacksonImpl extends AbstractJsonUtilImpl {
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
private volatile Object jacksonCache = null;
|
private volatile Object jacksonCache = null;
|
||||||
|
|
@ -71,6 +71,17 @@ public class JacksonImpl extends AbstractJSONImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Type type) {
|
||||||
|
JsonMapper mapper = getJackson();
|
||||||
|
return mapper.convertValue(obj, mapper.constructType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertObject(Object obj, Class<?> clazz) {
|
||||||
|
return getJackson().convertValue(obj, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
private JsonMapper getJackson() {
|
private JsonMapper getJackson() {
|
||||||
if (jacksonCache == null || !(jacksonCache instanceof JsonMapper)) {
|
if (jacksonCache == null || !(jacksonCache instanceof JsonMapper)) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,17 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.remoting.http;
|
package org.apache.dubbo.common.logger;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http invocation handler.
|
* Loggers that can register to listen to log messages.
|
||||||
*/
|
*/
|
||||||
public interface HttpHandler<REQUEST, RESPONSE> {
|
public interface ListenableLogger extends ErrorTypeAwareLogger {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* invoke.
|
* Register a listener to this logger,and get notified when a log happens.
|
||||||
*
|
*
|
||||||
* @param request request.
|
* @param listener log listener
|
||||||
* @param response response.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
void handle(REQUEST request, RESPONSE response) throws IOException;
|
void registerListen(LogListener listener);
|
||||||
}
|
}
|
||||||
|
|
@ -14,10 +14,12 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.protocol.rest.annotation;
|
package org.apache.dubbo.common.logger;
|
||||||
|
|
||||||
import org.apache.dubbo.metadata.rest.ArgInfo;
|
/**
|
||||||
|
* Log Listener, can registered to an {@link ListenableLogger}.
|
||||||
|
*/
|
||||||
|
public interface LogListener {
|
||||||
|
|
||||||
public interface ParamParser<T> {
|
void onMessage(String code, String msg);
|
||||||
void parse(T parseContext, ArgInfo argInfo);
|
|
||||||
}
|
}
|
||||||
|
|
@ -30,6 +30,14 @@ public interface Logger {
|
||||||
*/
|
*/
|
||||||
void trace(String msg);
|
void trace(String msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message with trace log level.
|
||||||
|
*
|
||||||
|
* @param msg log this message
|
||||||
|
* @param arguments a list of arguments
|
||||||
|
*/
|
||||||
|
void trace(String msg, Object... arguments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error with trace log level.
|
* Logs an error with trace log level.
|
||||||
*
|
*
|
||||||
|
|
@ -52,6 +60,14 @@ public interface Logger {
|
||||||
*/
|
*/
|
||||||
void debug(String msg);
|
void debug(String msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message with debug log level.
|
||||||
|
*
|
||||||
|
* @param msg log this message
|
||||||
|
* @param arguments a list of arguments
|
||||||
|
*/
|
||||||
|
void debug(String msg, Object... arguments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error with debug log level.
|
* Logs an error with debug log level.
|
||||||
*
|
*
|
||||||
|
|
@ -74,6 +90,14 @@ public interface Logger {
|
||||||
*/
|
*/
|
||||||
void info(String msg);
|
void info(String msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message with info log level.
|
||||||
|
*
|
||||||
|
* @param msg log this message
|
||||||
|
* @param arguments a list of arguments
|
||||||
|
*/
|
||||||
|
void info(String msg, Object... arguments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error with info log level.
|
* Logs an error with info log level.
|
||||||
*
|
*
|
||||||
|
|
@ -96,6 +120,14 @@ public interface Logger {
|
||||||
*/
|
*/
|
||||||
void warn(String msg);
|
void warn(String msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message with warn log level.
|
||||||
|
*
|
||||||
|
* @param msg log this message
|
||||||
|
* @param arguments a list of arguments
|
||||||
|
*/
|
||||||
|
void warn(String msg, Object... arguments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a message with warn log level.
|
* Logs a message with warn log level.
|
||||||
*
|
*
|
||||||
|
|
@ -118,6 +150,14 @@ public interface Logger {
|
||||||
*/
|
*/
|
||||||
void error(String msg);
|
void error(String msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message with error log level.
|
||||||
|
*
|
||||||
|
* @param msg log this message
|
||||||
|
* @param arguments a list of arguments
|
||||||
|
*/
|
||||||
|
void error(String msg, Object... arguments);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error with error log level.
|
* Logs an error with error log level.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.logger;
|
package org.apache.dubbo.common.logger;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
import org.apache.dubbo.common.logger.jcl.JclLoggerAdapter;
|
import org.apache.dubbo.common.logger.jcl.JclLoggerAdapter;
|
||||||
import org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter;
|
import org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter;
|
||||||
import org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter;
|
import org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter;
|
||||||
|
|
@ -24,6 +25,7 @@ import org.apache.dubbo.common.logger.slf4j.Slf4jLoggerAdapter;
|
||||||
import org.apache.dubbo.common.logger.support.FailsafeErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.support.FailsafeErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -47,7 +49,8 @@ public class LoggerFactory {
|
||||||
|
|
||||||
// search common-used logging frameworks
|
// search common-used logging frameworks
|
||||||
static {
|
static {
|
||||||
String logger = System.getProperty("dubbo.application.logger", "");
|
String logger =
|
||||||
|
SystemPropertyConfigUtils.getSystemProperty(CommonConstants.DubboProperty.DUBBO_APPLICATION_LOGGER, "");
|
||||||
switch (logger) {
|
switch (logger) {
|
||||||
case Slf4jLoggerAdapter.NAME:
|
case Slf4jLoggerAdapter.NAME:
|
||||||
setLoggerAdapter(new Slf4jLoggerAdapter());
|
setLoggerAdapter(new Slf4jLoggerAdapter());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2011 QOS.ch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.apache.dubbo.common.logger.helpers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the results of formatting done by {@link MessageFormatter}.
|
||||||
|
* This is a copy of org.slf4j.helpers.FormattingTuple from slf4j-api.
|
||||||
|
*
|
||||||
|
* @author Joern Huxhorn
|
||||||
|
*/
|
||||||
|
public class FormattingTuple {
|
||||||
|
|
||||||
|
static public FormattingTuple NULL = new FormattingTuple(null);
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
private Throwable throwable;
|
||||||
|
private Object[] argArray;
|
||||||
|
|
||||||
|
public FormattingTuple(String message) {
|
||||||
|
this(message, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormattingTuple(String message, Object[] argArray, Throwable throwable) {
|
||||||
|
this.message = message;
|
||||||
|
this.throwable = throwable;
|
||||||
|
this.argArray = argArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getArgArray() {
|
||||||
|
return argArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable getThrowable() {
|
||||||
|
return throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,437 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2011 QOS.ch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.apache.dubbo.common.logger.helpers;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// contributors: lizongbo: proposed special treatment of array parameter values
|
||||||
|
// Joern Huxhorn: pointed out double[] omission, suggested deep array copy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a copy of org.slf4j.helpers.MessageFormatter from slf4j-api.
|
||||||
|
* Formats messages according to very simple substitution rules. Substitutions
|
||||||
|
* can be made 1, 2 or more arguments.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example,
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("Hi {}.", "there")
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "Hi there.".
|
||||||
|
* <p>
|
||||||
|
* The {} pair is called the <em>formatting anchor</em>. It serves to designate
|
||||||
|
* the location where arguments need to be substituted within the message
|
||||||
|
* pattern.
|
||||||
|
* <p>
|
||||||
|
* In case your message contains the '{' or the '}' character, you do not have
|
||||||
|
* to do anything special unless the '}' character immediately follows '{'. For
|
||||||
|
* example,
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("Set {1,2,3} is not equal to {}.", "1,2");
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "Set {1,2,3} is not equal to 1,2.".
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* If for whatever reason you need to place the string "{}" in the message
|
||||||
|
* without its <em>formatting anchor</em> meaning, then you need to escape the
|
||||||
|
* '{' character with '\', that is the backslash character. Only the '{'
|
||||||
|
* character should be escaped. There is no need to escape the '}' character.
|
||||||
|
* For example,
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("Set \\{} is not equal to {}.", "1,2");
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "Set {} is not equal to 1,2.".
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The escaping behavior just described can be overridden by escaping the escape
|
||||||
|
* character '\'. Calling
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("File name is C:\\\\{}.", "file.zip");
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "File name is C:\file.zip".
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The formatting conventions are different than those of {@link MessageFormat}
|
||||||
|
* which ships with the Java platform. This is justified by the fact that
|
||||||
|
* SLF4J's implementation is 10 times faster than that of {@link MessageFormat}.
|
||||||
|
* This local performance difference is both measurable and significant in the
|
||||||
|
* larger context of the complete logging processing chain.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* See also {@link #format(String, Object)},
|
||||||
|
* {@link #format(String, Object, Object)} and
|
||||||
|
* {@link #arrayFormat(String, Object[])} methods for more details.
|
||||||
|
*
|
||||||
|
* @author Ceki Gülcü
|
||||||
|
* @author Joern Huxhorn
|
||||||
|
*/
|
||||||
|
final public class MessageFormatter {
|
||||||
|
static final char DELIM_START = '{';
|
||||||
|
static final char DELIM_STOP = '}';
|
||||||
|
static final String DELIM_STR = "{}";
|
||||||
|
private static final char ESCAPE_CHAR = '\\';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs single argument substitution for the 'messagePattern' passed as
|
||||||
|
* parameter.
|
||||||
|
* <p>
|
||||||
|
* For example,
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("Hi {}.", "there");
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "Hi there.".
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param messagePattern The message pattern which will be parsed and formatted
|
||||||
|
* @param arg The argument to be substituted in place of the formatting anchor
|
||||||
|
* @return The formatted message
|
||||||
|
*/
|
||||||
|
final public static FormattingTuple format(String messagePattern, Object arg) {
|
||||||
|
return arrayFormat(messagePattern, new Object[]{arg});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a two argument substitution for the 'messagePattern' passed as
|
||||||
|
* parameter.
|
||||||
|
* <p>
|
||||||
|
* For example,
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob");
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* will return the string "Hi Alice. My name is Bob.".
|
||||||
|
*
|
||||||
|
* @param messagePattern The message pattern which will be parsed and formatted
|
||||||
|
* @param arg1 The argument to be substituted in place of the first formatting
|
||||||
|
* anchor
|
||||||
|
* @param arg2 The argument to be substituted in place of the second formatting
|
||||||
|
* anchor
|
||||||
|
* @return The formatted message
|
||||||
|
*/
|
||||||
|
final public static FormattingTuple format(final String messagePattern, Object arg1, Object arg2) {
|
||||||
|
return arrayFormat(messagePattern, new Object[]{arg1, arg2});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray) {
|
||||||
|
Throwable throwableCandidate = MessageFormatter.getThrowableCandidate(argArray);
|
||||||
|
Object[] args = argArray;
|
||||||
|
if (throwableCandidate != null) {
|
||||||
|
args = MessageFormatter.trimmedCopy(argArray);
|
||||||
|
}
|
||||||
|
return arrayFormat(messagePattern, args, throwableCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray, Throwable throwable) {
|
||||||
|
|
||||||
|
if (messagePattern == null) {
|
||||||
|
return new FormattingTuple(null, argArray, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argArray == null) {
|
||||||
|
return new FormattingTuple(messagePattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int j;
|
||||||
|
// use string builder for better multicore performance
|
||||||
|
StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
|
||||||
|
|
||||||
|
int L;
|
||||||
|
for (L = 0; L < argArray.length; L++) {
|
||||||
|
|
||||||
|
j = messagePattern.indexOf(DELIM_STR, i);
|
||||||
|
|
||||||
|
if (j == -1) {
|
||||||
|
// no more variables
|
||||||
|
if (i == 0) { // this is a simple string
|
||||||
|
return new FormattingTuple(messagePattern, argArray, throwable);
|
||||||
|
} else { // add the tail string which contains no variables and return
|
||||||
|
// the result.
|
||||||
|
sbuf.append(messagePattern, i, messagePattern.length());
|
||||||
|
return new FormattingTuple(sbuf.toString(), argArray, throwable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isEscapedDelimeter(messagePattern, j)) {
|
||||||
|
if (!isDoubleEscaped(messagePattern, j)) {
|
||||||
|
L--; // DELIM_START was escaped, thus should not be incremented
|
||||||
|
sbuf.append(messagePattern, i, j - 1);
|
||||||
|
sbuf.append(DELIM_START);
|
||||||
|
i = j + 1;
|
||||||
|
} else {
|
||||||
|
// The escape character preceding the delimiter start is
|
||||||
|
// itself escaped: "abc x:\\{}"
|
||||||
|
// we have to consume one backward slash
|
||||||
|
sbuf.append(messagePattern, i, j - 1);
|
||||||
|
deeplyAppendParameter(sbuf, argArray[L], new HashMap<Object[], Object>());
|
||||||
|
i = j + 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// normal case
|
||||||
|
sbuf.append(messagePattern, i, j);
|
||||||
|
deeplyAppendParameter(sbuf, argArray[L], new HashMap<Object[], Object>());
|
||||||
|
i = j + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// append the characters following the last {} pair.
|
||||||
|
sbuf.append(messagePattern, i, messagePattern.length());
|
||||||
|
return new FormattingTuple(sbuf.toString(), argArray, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
final static boolean isEscapedDelimeter(String messagePattern, int delimeterStartIndex) {
|
||||||
|
|
||||||
|
if (delimeterStartIndex == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char potentialEscape = messagePattern.charAt(delimeterStartIndex - 1);
|
||||||
|
if (potentialEscape == ESCAPE_CHAR) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final static boolean isDoubleEscaped(String messagePattern, int delimeterStartIndex) {
|
||||||
|
if (delimeterStartIndex >= 2 && messagePattern.charAt(delimeterStartIndex - 2) == ESCAPE_CHAR) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// special treatment of array values was suggested by 'lizongbo'
|
||||||
|
private static void deeplyAppendParameter(StringBuilder sbuf, Object o, Map<Object[], Object> seenMap) {
|
||||||
|
if (o == null) {
|
||||||
|
sbuf.append("null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!o.getClass().isArray()) {
|
||||||
|
safeObjectAppend(sbuf, o);
|
||||||
|
} else {
|
||||||
|
// check for primitive array types because they
|
||||||
|
// unfortunately cannot be cast to Object[]
|
||||||
|
if (o instanceof boolean[]) {
|
||||||
|
booleanArrayAppend(sbuf, (boolean[]) o);
|
||||||
|
} else if (o instanceof byte[]) {
|
||||||
|
byteArrayAppend(sbuf, (byte[]) o);
|
||||||
|
} else if (o instanceof char[]) {
|
||||||
|
charArrayAppend(sbuf, (char[]) o);
|
||||||
|
} else if (o instanceof short[]) {
|
||||||
|
shortArrayAppend(sbuf, (short[]) o);
|
||||||
|
} else if (o instanceof int[]) {
|
||||||
|
intArrayAppend(sbuf, (int[]) o);
|
||||||
|
} else if (o instanceof long[]) {
|
||||||
|
longArrayAppend(sbuf, (long[]) o);
|
||||||
|
} else if (o instanceof float[]) {
|
||||||
|
floatArrayAppend(sbuf, (float[]) o);
|
||||||
|
} else if (o instanceof double[]) {
|
||||||
|
doubleArrayAppend(sbuf, (double[]) o);
|
||||||
|
} else {
|
||||||
|
objectArrayAppend(sbuf, (Object[]) o, seenMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void safeObjectAppend(StringBuilder sbuf, Object o) {
|
||||||
|
try {
|
||||||
|
String oAsString = o.toString();
|
||||||
|
sbuf.append(oAsString);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
System.err.println("SLF4J: Failed toString() invocation on an object of type [" + o.getClass().getName() + "]");
|
||||||
|
System.err.println("Reported exception:");
|
||||||
|
StackTraceElement[] stackTrace = t.getStackTrace();
|
||||||
|
StringBuilder stackBuilder = new StringBuilder();
|
||||||
|
for (StackTraceElement traceElement : stackTrace) {
|
||||||
|
stackBuilder.append("\tat ").append(traceElement).append("\n");
|
||||||
|
}
|
||||||
|
System.err.println(stackBuilder);
|
||||||
|
sbuf.append("[FAILED toString()]");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void objectArrayAppend(StringBuilder sbuf, Object[] a, Map<Object[], Object> seenMap) {
|
||||||
|
sbuf.append('[');
|
||||||
|
if (!seenMap.containsKey(a)) {
|
||||||
|
seenMap.put(a, null);
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
deeplyAppendParameter(sbuf, a[i], seenMap);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
// allow repeats in siblings
|
||||||
|
seenMap.remove(a);
|
||||||
|
} else {
|
||||||
|
sbuf.append("...");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void byteArrayAppend(StringBuilder sbuf, byte[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void charArrayAppend(StringBuilder sbuf, char[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void shortArrayAppend(StringBuilder sbuf, short[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void intArrayAppend(StringBuilder sbuf, int[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void longArrayAppend(StringBuilder sbuf, long[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void floatArrayAppend(StringBuilder sbuf, float[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doubleArrayAppend(StringBuilder sbuf, double[] a) {
|
||||||
|
sbuf.append('[');
|
||||||
|
final int len = a.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
sbuf.append(a[i]);
|
||||||
|
if (i != len - 1)
|
||||||
|
sbuf.append(", ");
|
||||||
|
}
|
||||||
|
sbuf.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to determine if an {@link Object} array contains a {@link Throwable} as last element
|
||||||
|
*
|
||||||
|
* @param argArray The arguments off which we want to know if it contains a {@link Throwable} as last element
|
||||||
|
* @return if the last {@link Object} in argArray is a {@link Throwable} this method will return it,
|
||||||
|
* otherwise it returns null
|
||||||
|
*/
|
||||||
|
public static Throwable getThrowableCandidate(final Object[] argArray) {
|
||||||
|
if (argArray == null || argArray.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object lastEntry = argArray[argArray.length - 1];
|
||||||
|
if (lastEntry instanceof Throwable) {
|
||||||
|
return (Throwable) lastEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to get all but the last element of an array
|
||||||
|
*
|
||||||
|
* @param argArray The arguments from which we want to remove the last element
|
||||||
|
* @return a copy of the array without the last element
|
||||||
|
*/
|
||||||
|
public static Object[] trimmedCopy(final Object[] argArray) {
|
||||||
|
if (argArray == null || argArray.length == 0) {
|
||||||
|
throw new IllegalStateException("non-sensical empty or null argument array");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int trimmedLen = argArray.length - 1;
|
||||||
|
|
||||||
|
Object[] trimmed = new Object[trimmedLen];
|
||||||
|
|
||||||
|
if (trimmedLen > 0) {
|
||||||
|
System.arraycopy(argArray, 0, trimmed, 0, trimmedLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@ package org.apache.dubbo.common.logger.jcl;
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.slf4j.helpers.FormattingTuple;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adaptor to commons logging, depends on commons-logging.jar. For more information about commons logging, pls. refer to
|
* Adaptor to commons logging, depends on commons-logging.jar. For more information about commons logging, pls. refer to
|
||||||
|
|
@ -37,6 +39,12 @@ public class JclLogger implements Logger {
|
||||||
logger.trace(msg);
|
logger.trace(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.trace(ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void trace(Throwable e) {
|
public void trace(Throwable e) {
|
||||||
logger.trace(e);
|
logger.trace(e);
|
||||||
|
|
@ -52,6 +60,12 @@ public class JclLogger implements Logger {
|
||||||
logger.debug(msg);
|
logger.debug(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.debug(ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Throwable e) {
|
public void debug(Throwable e) {
|
||||||
logger.debug(e);
|
logger.debug(e);
|
||||||
|
|
@ -67,6 +81,12 @@ public class JclLogger implements Logger {
|
||||||
logger.info(msg);
|
logger.info(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.info(ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Throwable e) {
|
public void info(Throwable e) {
|
||||||
logger.info(e);
|
logger.info(e);
|
||||||
|
|
@ -82,6 +102,12 @@ public class JclLogger implements Logger {
|
||||||
logger.warn(msg);
|
logger.warn(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.warn(ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Throwable e) {
|
public void warn(Throwable e) {
|
||||||
logger.warn(e);
|
logger.warn(e);
|
||||||
|
|
@ -97,6 +123,12 @@ public class JclLogger implements Logger {
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.error(ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Throwable e) {
|
public void error(Throwable e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ import org.apache.dubbo.common.logger.Logger;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.slf4j.helpers.FormattingTuple;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
public class JdkLogger implements Logger {
|
public class JdkLogger implements Logger {
|
||||||
|
|
||||||
private final java.util.logging.Logger logger;
|
private final java.util.logging.Logger logger;
|
||||||
|
|
@ -33,6 +36,12 @@ public class JdkLogger implements Logger {
|
||||||
logger.log(Level.FINER, msg);
|
logger.log(Level.FINER, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(Level.FINER, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void trace(Throwable e) {
|
public void trace(Throwable e) {
|
||||||
logger.log(Level.FINER, e.getMessage(), e);
|
logger.log(Level.FINER, e.getMessage(), e);
|
||||||
|
|
@ -48,6 +57,12 @@ public class JdkLogger implements Logger {
|
||||||
logger.log(Level.FINE, msg);
|
logger.log(Level.FINE, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(Level.FINE, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Throwable e) {
|
public void debug(Throwable e) {
|
||||||
logger.log(Level.FINE, e.getMessage(), e);
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
|
|
@ -63,6 +78,12 @@ public class JdkLogger implements Logger {
|
||||||
logger.log(Level.INFO, msg);
|
logger.log(Level.INFO, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(Level.INFO, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(String msg, Throwable e) {
|
public void info(String msg, Throwable e) {
|
||||||
logger.log(Level.INFO, msg, e);
|
logger.log(Level.INFO, msg, e);
|
||||||
|
|
@ -73,6 +94,12 @@ public class JdkLogger implements Logger {
|
||||||
logger.log(Level.WARNING, msg);
|
logger.log(Level.WARNING, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(Level.WARNING, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(String msg, Throwable e) {
|
public void warn(String msg, Throwable e) {
|
||||||
logger.log(Level.WARNING, msg, e);
|
logger.log(Level.WARNING, msg, e);
|
||||||
|
|
@ -83,6 +110,12 @@ public class JdkLogger implements Logger {
|
||||||
logger.log(Level.SEVERE, msg);
|
logger.log(Level.SEVERE, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(Level.SEVERE, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String msg, Throwable e) {
|
public void error(String msg, Throwable e) {
|
||||||
logger.log(Level.SEVERE, msg, e);
|
logger.log(Level.SEVERE, msg, e);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
||||||
|
|
||||||
import org.apache.log4j.Level;
|
import org.apache.log4j.Level;
|
||||||
|
import org.slf4j.helpers.FormattingTuple;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
public class Log4jLogger implements Logger {
|
public class Log4jLogger implements Logger {
|
||||||
|
|
||||||
|
|
@ -36,6 +38,12 @@ public class Log4jLogger implements Logger {
|
||||||
logger.log(FQCN, Level.TRACE, msg, null);
|
logger.log(FQCN, Level.TRACE, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(FQCN, Level.TRACE, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void trace(Throwable e) {
|
public void trace(Throwable e) {
|
||||||
logger.log(FQCN, Level.TRACE, e == null ? null : e.getMessage(), e);
|
logger.log(FQCN, Level.TRACE, e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -51,6 +59,12 @@ public class Log4jLogger implements Logger {
|
||||||
logger.log(FQCN, Level.DEBUG, msg, null);
|
logger.log(FQCN, Level.DEBUG, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Throwable e) {
|
public void debug(Throwable e) {
|
||||||
logger.log(FQCN, Level.DEBUG, e == null ? null : e.getMessage(), e);
|
logger.log(FQCN, Level.DEBUG, e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -66,6 +80,12 @@ public class Log4jLogger implements Logger {
|
||||||
logger.log(FQCN, Level.INFO, msg, null);
|
logger.log(FQCN, Level.INFO, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Throwable e) {
|
public void info(Throwable e) {
|
||||||
logger.log(FQCN, Level.INFO, e == null ? null : e.getMessage(), e);
|
logger.log(FQCN, Level.INFO, e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -81,6 +101,12 @@ public class Log4jLogger implements Logger {
|
||||||
logger.log(FQCN, Level.WARN, msg, null);
|
logger.log(FQCN, Level.WARN, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Throwable e) {
|
public void warn(Throwable e) {
|
||||||
logger.log(FQCN, Level.WARN, e == null ? null : e.getMessage(), e);
|
logger.log(FQCN, Level.WARN, e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -96,6 +122,12 @@ public class Log4jLogger implements Logger {
|
||||||
logger.log(FQCN, Level.ERROR, msg, null);
|
logger.log(FQCN, Level.ERROR, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Throwable e) {
|
public void error(Throwable e) {
|
||||||
logger.log(FQCN, Level.ERROR, e == null ? null : e.getMessage(), e);
|
logger.log(FQCN, Level.ERROR, e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -130,9 +162,4 @@ public class Log4jLogger implements Logger {
|
||||||
public boolean isErrorEnabled() {
|
public boolean isErrorEnabled() {
|
||||||
return logger.isEnabledFor(Level.ERROR);
|
return logger.isEnabledFor(Level.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test purpose only
|
|
||||||
public org.apache.log4j.Logger getLogger() {
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ public class Log4j2Logger implements Logger {
|
||||||
logger.trace(msg);
|
logger.trace(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
logger.trace(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void trace(Throwable e) {
|
public void trace(Throwable e) {
|
||||||
logger.trace(e == null ? null : e.getMessage(), e);
|
logger.trace(e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -46,6 +51,11 @@ public class Log4j2Logger implements Logger {
|
||||||
logger.debug(msg);
|
logger.debug(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
logger.debug(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Throwable e) {
|
public void debug(Throwable e) {
|
||||||
logger.debug(e == null ? null : e.getMessage(), e);
|
logger.debug(e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -61,6 +71,11 @@ public class Log4j2Logger implements Logger {
|
||||||
logger.info(msg);
|
logger.info(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
logger.info(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Throwable e) {
|
public void info(Throwable e) {
|
||||||
logger.info(e == null ? null : e.getMessage(), e);
|
logger.info(e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -76,6 +91,11 @@ public class Log4j2Logger implements Logger {
|
||||||
logger.warn(msg);
|
logger.warn(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
logger.warn(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Throwable e) {
|
public void warn(Throwable e) {
|
||||||
logger.warn(e == null ? null : e.getMessage(), e);
|
logger.warn(e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -91,6 +111,11 @@ public class Log4j2Logger implements Logger {
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
logger.error(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Throwable e) {
|
public void error(Throwable e) {
|
||||||
logger.error(e == null ? null : e.getMessage(), e);
|
logger.error(e == null ? null : e.getMessage(), e);
|
||||||
|
|
@ -125,4 +150,9 @@ public class Log4j2Logger implements Logger {
|
||||||
public boolean isErrorEnabled() {
|
public boolean isErrorEnabled() {
|
||||||
return logger.isErrorEnabled();
|
return logger.isErrorEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test purpose only
|
||||||
|
public org.apache.logging.log4j.Logger getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import org.apache.dubbo.common.logger.Level;
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
import org.apache.dubbo.common.logger.support.FailsafeLogger;
|
||||||
|
|
||||||
|
import org.slf4j.helpers.FormattingTuple;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
import org.slf4j.spi.LocationAwareLogger;
|
import org.slf4j.spi.LocationAwareLogger;
|
||||||
|
|
||||||
public class Slf4jLogger implements Logger {
|
public class Slf4jLogger implements Logger {
|
||||||
|
|
@ -48,6 +50,17 @@ public class Slf4jLogger implements Logger {
|
||||||
logger.trace(msg);
|
logger.trace(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
if (locationAwareLogger != null) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
locationAwareLogger.log(
|
||||||
|
null, FQCN, LocationAwareLogger.TRACE_INT, msg, ft.getArgArray(), ft.getThrowable());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.trace(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void trace(Throwable e) {
|
public void trace(Throwable e) {
|
||||||
if (locationAwareLogger != null) {
|
if (locationAwareLogger != null) {
|
||||||
|
|
@ -75,6 +88,17 @@ public class Slf4jLogger implements Logger {
|
||||||
logger.debug(msg);
|
logger.debug(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
if (locationAwareLogger != null) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
locationAwareLogger.log(
|
||||||
|
null, FQCN, LocationAwareLogger.DEBUG_INT, msg, ft.getArgArray(), ft.getThrowable());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Throwable e) {
|
public void debug(Throwable e) {
|
||||||
if (locationAwareLogger != null) {
|
if (locationAwareLogger != null) {
|
||||||
|
|
@ -102,6 +126,16 @@ public class Slf4jLogger implements Logger {
|
||||||
logger.info(msg);
|
logger.info(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
if (locationAwareLogger != null) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, ft.getArgArray(), ft.getThrowable());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Throwable e) {
|
public void info(Throwable e) {
|
||||||
if (locationAwareLogger != null) {
|
if (locationAwareLogger != null) {
|
||||||
|
|
@ -129,6 +163,16 @@ public class Slf4jLogger implements Logger {
|
||||||
logger.warn(msg);
|
logger.warn(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
if (locationAwareLogger != null) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, ft.getArgArray(), ft.getThrowable());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.warn(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Throwable e) {
|
public void warn(Throwable e) {
|
||||||
if (locationAwareLogger != null) {
|
if (locationAwareLogger != null) {
|
||||||
|
|
@ -156,6 +200,17 @@ public class Slf4jLogger implements Logger {
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
if (locationAwareLogger != null) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments);
|
||||||
|
locationAwareLogger.log(
|
||||||
|
null, FQCN, LocationAwareLogger.ERROR_INT, msg, ft.getArgArray(), ft.getThrowable());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.error(msg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Throwable e) {
|
public void error(Throwable e) {
|
||||||
if (locationAwareLogger != null) {
|
if (locationAwareLogger != null) {
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,22 @@
|
||||||
package org.apache.dubbo.common.logger.support;
|
package org.apache.dubbo.common.logger.support;
|
||||||
|
|
||||||
import org.apache.dubbo.common.Version;
|
import org.apache.dubbo.common.Version;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ListenableLogger;
|
||||||
|
import org.apache.dubbo.common.logger.LogListener;
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.utils.NetUtils;
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fail-safe (ignoring exception thrown by logger) wrapper of error type aware logger.
|
* A fail-safe (ignoring exception thrown by logger) wrapper of error type aware logger.
|
||||||
*/
|
*/
|
||||||
public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ErrorTypeAwareLogger {
|
public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ListenableLogger {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template address for formatting.
|
* Template address for formatting.
|
||||||
|
|
@ -35,6 +41,16 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
|
||||||
|
|
||||||
private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("\\d+-\\d+");
|
private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("\\d+-\\d+");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listeners that listened to all Loggers.
|
||||||
|
*/
|
||||||
|
private static final List<LogListener> GLOBAL_LISTENERS = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listeners that listened to this listener.
|
||||||
|
*/
|
||||||
|
private final AtomicReference<List<LogListener>> listeners = new AtomicReference<>();
|
||||||
|
|
||||||
public FailsafeErrorTypeAwareLogger(Logger logger) {
|
public FailsafeErrorTypeAwareLogger(Logger logger) {
|
||||||
super(logger);
|
super(logger);
|
||||||
}
|
}
|
||||||
|
|
@ -81,6 +97,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
onEvent(code, msg);
|
||||||
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
|
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// ignored.
|
// ignored.
|
||||||
|
|
@ -94,6 +111,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
onEvent(code, msg);
|
||||||
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
|
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// ignored.
|
// ignored.
|
||||||
|
|
@ -107,6 +125,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
onEvent(code, msg);
|
||||||
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
|
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// ignored.
|
// ignored.
|
||||||
|
|
@ -120,9 +139,44 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
onEvent(code, msg);
|
||||||
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
|
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// ignored.
|
// ignored.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerGlobalListen(LogListener listener) {
|
||||||
|
GLOBAL_LISTENERS.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerListen(LogListener listener) {
|
||||||
|
listeners.getAndUpdate(logListeners -> {
|
||||||
|
if (logListeners == null) {
|
||||||
|
logListeners = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
}
|
||||||
|
logListeners.add(listener);
|
||||||
|
return logListeners;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEvent(String code, String msg) {
|
||||||
|
Optional.ofNullable(listeners.get())
|
||||||
|
.ifPresent(logListeners -> logListeners.forEach(logListener -> {
|
||||||
|
try {
|
||||||
|
logListener.onMessage(code, msg);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignored.
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
GLOBAL_LISTENERS.forEach(logListener -> {
|
||||||
|
try {
|
||||||
|
logListener.onMessage(code, msg);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignored.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,17 @@ public class FailsafeLogger implements Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String msg, Object... arguments) {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
logger.trace(appendContextMessage(msg), arguments);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(String msg, Throwable e) {
|
public void debug(String msg, Throwable e) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -117,6 +128,17 @@ public class FailsafeLogger implements Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String msg, Object... arguments) {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
logger.debug(appendContextMessage(msg), arguments);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(String msg, Throwable e) {
|
public void info(String msg, Throwable e) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -139,6 +161,17 @@ public class FailsafeLogger implements Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String msg, Object... arguments) {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
logger.info(appendContextMessage(msg), arguments);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(String msg, Throwable e) {
|
public void warn(String msg, Throwable e) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -161,6 +194,17 @@ public class FailsafeLogger implements Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String msg, Object... arguments) {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
logger.warn(appendContextMessage(msg), arguments);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String msg, Throwable e) {
|
public void error(String msg, Throwable e) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -183,6 +227,17 @@ public class FailsafeLogger implements Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String msg, Object... arguments) {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
logger.error(appendContextMessage(msg), arguments);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Throwable e) {
|
public void error(Throwable e) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
|
||||||
|
|
@ -14,37 +14,33 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.remoting.http.servlet;
|
package org.apache.dubbo.common.serialization;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
public class ClassHolder {
|
||||||
* TODO this may not be a pretty elegant solution,
|
private final Map<String, Set<Class<?>>> classCache = new ConcurrentHashMap<>();
|
||||||
*/
|
|
||||||
public class ServletManager {
|
|
||||||
|
|
||||||
public static final int EXTERNAL_SERVER_PORT = -1234;
|
public void storeClass(Class<?> clazz) {
|
||||||
|
classCache
|
||||||
private static final ServletManager INSTANCE = new ServletManager();
|
.computeIfAbsent(clazz.getName(), k -> new ConcurrentHashSet<>())
|
||||||
|
.add(clazz);
|
||||||
private final Map<Integer, ServletContext> contextMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public static ServletManager getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addServletContext(int port, ServletContext servletContext) {
|
public Class<?> loadClass(String className, ClassLoader classLoader) {
|
||||||
contextMap.put(port, servletContext);
|
Set<Class<?>> classList = classCache.get(className);
|
||||||
}
|
if (classList == null) {
|
||||||
|
return null;
|
||||||
public void removeServletContext(int port) {
|
}
|
||||||
contextMap.remove(port);
|
for (Class<?> clazz : classList) {
|
||||||
}
|
if (classLoader.equals(clazz.getClassLoader())) {
|
||||||
|
return clazz;
|
||||||
public ServletContext getServletContext(int port) {
|
}
|
||||||
return contextMap.get(port);
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
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.URL;
|
||||||
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
|
@ -25,6 +26,7 @@ import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedListener;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
import org.apache.dubbo.common.utils.JVMUtil;
|
import org.apache.dubbo.common.utils.JVMUtil;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -42,8 +44,8 @@ import static java.lang.String.format;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
|
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
|
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_ENABLE;
|
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_ENABLE;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY;
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.OS_WIN_PREFIX;
|
import static org.apache.dubbo.common.constants.CommonConstants.OS_WIN_PREFIX;
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.SystemProperty.SYSTEM_OS_NAME;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.THREAD_POOL_EXHAUSTED_LISTENERS_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.THREAD_POOL_EXHAUSTED_LISTENERS_KEY;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_THREAD_POOL_EXHAUSTED;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_THREAD_POOL_EXHAUSTED;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_CREATE_DUMP;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_CREATE_DUMP;
|
||||||
|
|
@ -71,7 +73,8 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
|
||||||
|
|
||||||
protected static Semaphore guard = new Semaphore(1);
|
protected static Semaphore guard = new Semaphore(1);
|
||||||
|
|
||||||
private static final String USER_HOME = System.getProperty("user.home");
|
private static final String USER_HOME =
|
||||||
|
SystemPropertyConfigUtils.getSystemProperty(CommonConstants.SystemProperty.USER_HOME);
|
||||||
|
|
||||||
private final Set<ThreadPoolExhaustedListener> listeners = new ConcurrentHashSet<>();
|
private final Set<ThreadPoolExhaustedListener> listeners = new ConcurrentHashSet<>();
|
||||||
|
|
||||||
|
|
@ -168,7 +171,8 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
|
||||||
|
|
||||||
SimpleDateFormat sdf;
|
SimpleDateFormat sdf;
|
||||||
|
|
||||||
String os = System.getProperty(OS_NAME_KEY).toLowerCase();
|
String os = SystemPropertyConfigUtils.getSystemProperty(SYSTEM_OS_NAME)
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
// window system don't support ":" in file name
|
// window system don't support ":" in file name
|
||||||
if (os.contains(OS_WIN_PREFIX)) {
|
if (os.contains(OS_WIN_PREFIX)) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.common.timer;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.ClassUtils;
|
import org.apache.dubbo.common.utils.ClassUtils;
|
||||||
|
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -36,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.SystemProperty.SYSTEM_OS_NAME;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.OS_WIN_PREFIX;
|
import static org.apache.dubbo.common.constants.CommonConstants.OS_WIN_PREFIX;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_RUN_THREAD_TASK;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_RUN_THREAD_TASK;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_TOO_MANY_INSTANCES;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_TOO_MANY_INSTANCES;
|
||||||
|
|
@ -811,7 +812,7 @@ public class HashedWheelTimer implements Timer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final boolean IS_OS_WINDOWS = System.getProperty(OS_NAME_KEY, "").toLowerCase(Locale.US).contains(OS_WIN_PREFIX);
|
private static final boolean IS_OS_WINDOWS = SystemPropertyConfigUtils.getSystemProperty(SYSTEM_OS_NAME, "").toLowerCase(Locale.US).contains(OS_WIN_PREFIX);
|
||||||
|
|
||||||
private boolean isWindows() {
|
private boolean isWindows() {
|
||||||
return IS_OS_WINDOWS;
|
return IS_OS_WINDOWS;
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,38 @@ public interface AnnotationUtils {
|
||||||
return getAttribute(annotation, "value");
|
return getAttribute(annotation, "value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attribute from the specified {@link Annotation annotation}
|
||||||
|
*
|
||||||
|
* @param annotation the specified {@link Annotation annotation}
|
||||||
|
* @param attributeNames the multiply attribute name arrays
|
||||||
|
* @param <T> the type of attribute
|
||||||
|
* @return the attribute value
|
||||||
|
* @throws IllegalArgumentException If the attribute name can't be found
|
||||||
|
*/
|
||||||
|
static <T> T getAttribute(Annotation annotation, String... attributeNames) throws IllegalArgumentException {
|
||||||
|
if (attributeNames == null || attributeNames.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String attributeName : attributeNames) {
|
||||||
|
T attribute = getAttribute(annotation, attributeName);
|
||||||
|
|
||||||
|
if (attribute == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exclude string attribute default is empty
|
||||||
|
if ((attribute instanceof String) && ((String) attribute).length() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Annotation} from the specified {@link AnnotatedElement the annotated element} and
|
* Get the {@link Annotation} from the specified {@link AnnotatedElement the annotated element} and
|
||||||
* {@link Annotation annotation} class name
|
* {@link Annotation annotation} class name
|
||||||
|
|
|
||||||
|
|
@ -76,4 +76,8 @@ public final class ArrayUtils {
|
||||||
public static <T> T[] of(T... values) {
|
public static <T> T[] of(T... values) {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> T first(T[] data) {
|
||||||
|
return isEmpty(data) ? null : data[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ public abstract class Assert {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void notNull(Object obj, String format, Object... args) {
|
||||||
|
if (obj == null) {
|
||||||
|
throw new IllegalArgumentException(String.format(format, args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void notEmptyString(String str, String message) {
|
public static void notEmptyString(String str, String message) {
|
||||||
if (StringUtils.isEmpty(str)) {
|
if (StringUtils.isEmpty(str)) {
|
||||||
throw new IllegalArgumentException(message);
|
throw new IllegalArgumentException(message);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import org.apache.dubbo.common.resource.GlobalResourcesRepository;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -31,7 +30,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
|
@ -80,15 +78,9 @@ public class ClassLoaderResourceLoader {
|
||||||
Enumeration<URL> urls;
|
Enumeration<URL> urls;
|
||||||
try {
|
try {
|
||||||
urls = currentClassLoader.getResources(fileName);
|
urls = currentClassLoader.getResources(fileName);
|
||||||
boolean isNative = NativeUtils.isNative();
|
|
||||||
if (urls != null) {
|
if (urls != null) {
|
||||||
while (urls.hasMoreElements()) {
|
while (urls.hasMoreElements()) {
|
||||||
URL url = urls.nextElement();
|
URL url = urls.nextElement();
|
||||||
if (isNative) {
|
|
||||||
// In native mode, the address of each URL is the same instead of different paths, so it is
|
|
||||||
// necessary to set the ref to make it different
|
|
||||||
setRef(url);
|
|
||||||
}
|
|
||||||
set.add(url);
|
set.add(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,15 +104,6 @@ public class ClassLoaderResourceLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setRef(URL url) {
|
|
||||||
try {
|
|
||||||
Field field = URL.class.getDeclaredField("ref");
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(url, UUID.randomUUID().toString());
|
|
||||||
} catch (Throwable ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test
|
// for test
|
||||||
protected static SoftReference<Map<ClassLoader, Map<String, Set<URL>>>> getClassLoaderResourcesCache() {
|
protected static SoftReference<Map<ClassLoader, Map<String, Set<URL>>>> getClassLoaderResourcesCache() {
|
||||||
return classLoaderResourcesCache;
|
return classLoaderResourcesCache;
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,19 @@ public class ClassUtils {
|
||||||
return forName(name, getClassLoader());
|
return forName(name, getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find class and don`t expect to throw exception
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Class<?> forNameAndTryCatch(String name) {
|
||||||
|
try {
|
||||||
|
return forName(name, getClassLoader());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replacement for <code>Class.forName()</code> that also returns Class
|
* Replacement for <code>Class.forName()</code> that also returns Class
|
||||||
* instances for primitives (like "int") and array class names (like
|
* instances for primitives (like "int") and array class names (like
|
||||||
|
|
@ -314,6 +327,10 @@ public class ClassUtils {
|
||||||
return type != null && (type.isPrimitive() || isSimpleType(type));
|
return type != null && (type.isPrimitive() || isSimpleType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isPrimitiveWrapper(Class<?> type) {
|
||||||
|
return PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The specified type is simple type or not
|
* The specified type is simple type or not
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,14 @@ import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.util.Collections.emptySet;
|
import static java.util.Collections.emptySet;
|
||||||
|
|
@ -404,13 +407,19 @@ public class CollectionUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (values instanceof List) {
|
if (values instanceof List) {
|
||||||
List<T> list = (List<T>) values;
|
return ((List<T>) values).get(0);
|
||||||
return list.get(0);
|
|
||||||
} else {
|
} else {
|
||||||
return values.iterator().next();
|
return values.iterator().next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> T first(List<T> values) {
|
||||||
|
if (isEmpty(values)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return values.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> Set<T> toTreeSet(Set<T> set) {
|
public static <T> Set<T> toTreeSet(Set<T> set) {
|
||||||
if (isEmpty(set)) {
|
if (isEmpty(set)) {
|
||||||
return set;
|
return set;
|
||||||
|
|
@ -420,4 +429,78 @@ public class CollectionUtils {
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> Set<T> newHashSet(int expectedSize) {
|
||||||
|
return new HashSet<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Set<T> newLinkedHashSet(int expectedSize) {
|
||||||
|
return new LinkedHashSet<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> newHashMap(int expectedSize) {
|
||||||
|
return new HashMap<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> newLinkedHashMap(int expectedSize) {
|
||||||
|
return new LinkedHashMap<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> newConcurrentHashMap(int expectedSize) {
|
||||||
|
if (JRE.JAVA_8.isCurrentVersion()) {
|
||||||
|
return new SafeConcurrentHashMap<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
return new ConcurrentHashMap<>(capacity(expectedSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> newConcurrentHashMap() {
|
||||||
|
if (JRE.JAVA_8.isCurrentVersion()) {
|
||||||
|
return new SafeConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
return new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int capacity(int expectedSize) {
|
||||||
|
if (expectedSize < 3) {
|
||||||
|
if (expectedSize < 0) {
|
||||||
|
throw new IllegalArgumentException("expectedSize cannot be negative but was: " + expectedSize);
|
||||||
|
}
|
||||||
|
return expectedSize + 1;
|
||||||
|
}
|
||||||
|
if (expectedSize < 1 << (Integer.SIZE - 2)) {
|
||||||
|
return (int) (expectedSize / 0.75F + 1.0F);
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public SafeConcurrentHashMap() {}
|
||||||
|
|
||||||
|
public SafeConcurrentHashMap(int initialCapacity) {
|
||||||
|
super(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SafeConcurrentHashMap(Map<? extends K, ? extends V> m) {
|
||||||
|
super(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||||
|
V value = get(key);
|
||||||
|
if (value != null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value = mappingFunction.apply(key);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
V exists = putIfAbsent(key, value);
|
||||||
|
if (exists != null) {
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,9 +164,9 @@ public class ConfigUtils {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Properties getProperties(Set<ClassLoader> classLoaders) {
|
public static Properties getProperties(Set<ClassLoader> classLoaders) {
|
||||||
String path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
|
String path = SystemPropertyConfigUtils.getSystemProperty(CommonConstants.DubboProperty.DUBBO_PROPERTIES_KEY);
|
||||||
if (StringUtils.isEmpty(path)) {
|
if (StringUtils.isEmpty(path)) {
|
||||||
path = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY);
|
path = System.getenv(CommonConstants.DubboProperty.DUBBO_PROPERTIES_KEY);
|
||||||
if (StringUtils.isEmpty(path)) {
|
if (StringUtils.isEmpty(path)) {
|
||||||
path = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
|
path = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.temporal.ChronoField;
|
||||||
|
import java.time.temporal.TemporalAccessor;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
|
public final class DateUtils {
|
||||||
|
|
||||||
|
public static final ZoneId GMT = ZoneId.of("GMT");
|
||||||
|
public static final ZoneId UTC = ZoneId.of("UTC");
|
||||||
|
|
||||||
|
public static final String DATE = "yyyy-MM-dd";
|
||||||
|
public static final String DATE_MIN = "yyyy-MM-dd HH:mm";
|
||||||
|
public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
public static final String JDK_TIME = "EEE MMM dd HH:mm:ss zzz yyyy";
|
||||||
|
public static final String ASC_TIME = "EEE MMM d HH:mm:ss yyyy";
|
||||||
|
public static final String RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
|
||||||
|
|
||||||
|
public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DATE);
|
||||||
|
public static final DateTimeFormatter DATE_MIN_FORMAT = DateTimeFormatter.ofPattern(DATE_MIN);
|
||||||
|
public static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern(DATE_TIME);
|
||||||
|
public static final DateTimeFormatter JDK_TIME_FORMAT = DateTimeFormatter.ofPattern(JDK_TIME, Locale.US);
|
||||||
|
public static final DateTimeFormatter ASC_TIME_FORMAT = DateTimeFormatter.ofPattern(ASC_TIME, Locale.US);
|
||||||
|
public static final DateTimeFormatter RFC1036_FORMAT = DateTimeFormatter.ofPattern(RFC1036, Locale.US);
|
||||||
|
|
||||||
|
private static final Map<String, DateTimeFormatter> CACHE = new LRUCache<>(64);
|
||||||
|
private static final List<DateTimeFormatter> CUSTOM_FORMATTERS = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
private DateUtils() {}
|
||||||
|
|
||||||
|
public static void registerFormatter(String pattern) {
|
||||||
|
CUSTOM_FORMATTERS.add(DateTimeFormatter.ofPattern(pattern));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerFormatter(DateTimeFormatter formatter) {
|
||||||
|
CUSTOM_FORMATTERS.add(formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date parse(String str, String pattern) {
|
||||||
|
if (DATE_TIME.equals(pattern)) {
|
||||||
|
return parse(str, DATE_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = getFormatter(pattern);
|
||||||
|
return parse(str, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date parse(String str, DateTimeFormatter formatter) {
|
||||||
|
return toDate(formatter.parse(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(Date date) {
|
||||||
|
return format(date, DATE_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(Date date, String pattern) {
|
||||||
|
if (DATE_TIME.equals(pattern)) {
|
||||||
|
return format(date, DATE_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = getFormatter(pattern);
|
||||||
|
return format(date, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(Date date, DateTimeFormatter formatter) {
|
||||||
|
return formatter.format(ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(Date date, DateTimeFormatter formatter, ZoneId zone) {
|
||||||
|
return formatter.format(ZonedDateTime.ofInstant(date.toInstant(), zone));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatGMT(Date date, DateTimeFormatter formatter) {
|
||||||
|
return formatter.format(ZonedDateTime.ofInstant(date.toInstant(), GMT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatUTC(Date date, DateTimeFormatter formatter) {
|
||||||
|
return formatter.format(ZonedDateTime.ofInstant(date.toInstant(), UTC));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatHeader(Date date) {
|
||||||
|
return DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.ofInstant(date.toInstant(), GMT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTimeFormatter getFormatter(String pattern) {
|
||||||
|
return CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date parse(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return (Date) value;
|
||||||
|
}
|
||||||
|
if (value instanceof Calendar) {
|
||||||
|
return ((Calendar) value).getTime();
|
||||||
|
}
|
||||||
|
if (value.getClass() == Instant.class) {
|
||||||
|
return Date.from((Instant) value);
|
||||||
|
}
|
||||||
|
if (value instanceof TemporalAccessor) {
|
||||||
|
return Date.from(Instant.from((TemporalAccessor) value));
|
||||||
|
}
|
||||||
|
if (value instanceof Number) {
|
||||||
|
return new Date(((Number) value).longValue());
|
||||||
|
}
|
||||||
|
if (value instanceof CharSequence) {
|
||||||
|
return parse(value.toString());
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Can not cast to Date, value : '" + value + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date parse(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String str = value.trim();
|
||||||
|
int len = str.length();
|
||||||
|
if (len == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isIso = true;
|
||||||
|
boolean isNumeric = true;
|
||||||
|
boolean hasDate = false;
|
||||||
|
boolean hasTime = false;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case ' ':
|
||||||
|
isIso = false;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
hasDate = true;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
case ':':
|
||||||
|
hasTime = true;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if (isNumeric) {
|
||||||
|
isNumeric = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = null;
|
||||||
|
if (isIso) {
|
||||||
|
if (hasDate) {
|
||||||
|
formatter = hasTime ? DateTimeFormatter.ISO_DATE_TIME : DateTimeFormatter.ISO_DATE;
|
||||||
|
} else if (hasTime) {
|
||||||
|
formatter = DateTimeFormatter.ISO_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNumeric) {
|
||||||
|
long num = Long.parseLong(str);
|
||||||
|
if (num > 21000101 || num < 19700101) {
|
||||||
|
return new Date(num);
|
||||||
|
}
|
||||||
|
formatter = DateTimeFormatter.BASIC_ISO_DATE;
|
||||||
|
}
|
||||||
|
switch (len) {
|
||||||
|
case 10:
|
||||||
|
formatter = DATE_FORMAT;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
formatter = DATE_MIN_FORMAT;
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
formatter = DATE_TIME_FORMAT;
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
case 24:
|
||||||
|
formatter = ASC_TIME_FORMAT;
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
formatter = RFC1036_FORMAT;
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
formatter = JDK_TIME_FORMAT;
|
||||||
|
break;
|
||||||
|
case 29:
|
||||||
|
formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatter != null) {
|
||||||
|
try {
|
||||||
|
return toDate(formatter.parse(str));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (DateTimeFormatter dtf : CUSTOM_FORMATTERS) {
|
||||||
|
try {
|
||||||
|
return parse(str, dtf);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Can not cast to Date, value : '" + value + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date toDate(TemporalAccessor temporal) {
|
||||||
|
if (temporal instanceof Instant) {
|
||||||
|
return Date.from((Instant) temporal);
|
||||||
|
}
|
||||||
|
long timestamp;
|
||||||
|
if (temporal.isSupported(ChronoField.EPOCH_DAY)) {
|
||||||
|
timestamp = temporal.getLong(ChronoField.EPOCH_DAY) * 86400000;
|
||||||
|
} else {
|
||||||
|
timestamp = LocalDate.now().toEpochDay() * 86400000;
|
||||||
|
}
|
||||||
|
if (temporal.isSupported(ChronoField.MILLI_OF_DAY)) {
|
||||||
|
timestamp += temporal.getLong(ChronoField.MILLI_OF_DAY);
|
||||||
|
}
|
||||||
|
if (temporal.isSupported(ChronoField.OFFSET_SECONDS)) {
|
||||||
|
timestamp -= temporal.getLong(ChronoField.OFFSET_SECONDS) * 1000;
|
||||||
|
} else {
|
||||||
|
timestamp -= TimeZone.getDefault().getRawOffset();
|
||||||
|
}
|
||||||
|
return new Date(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,10 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.utils;
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.aot.NativeDetector;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
import org.apache.dubbo.common.serialization.ClassHolder;
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -40,6 +42,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
private volatile boolean checkSerializable = true;
|
private volatile boolean checkSerializable = true;
|
||||||
|
|
||||||
private final SerializeSecurityManager serializeSecurityManager;
|
private final SerializeSecurityManager serializeSecurityManager;
|
||||||
|
private final ClassHolder classHolder;
|
||||||
private volatile long[] allowPrefixes = new long[0];
|
private volatile long[] allowPrefixes = new long[0];
|
||||||
|
|
||||||
private volatile long[] disAllowPrefixes = new long[0];
|
private volatile long[] disAllowPrefixes = new long[0];
|
||||||
|
|
@ -47,6 +50,8 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
public DefaultSerializeClassChecker(FrameworkModel frameworkModel) {
|
public DefaultSerializeClassChecker(FrameworkModel frameworkModel) {
|
||||||
serializeSecurityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class);
|
serializeSecurityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class);
|
||||||
serializeSecurityManager.registerListener(this);
|
serializeSecurityManager.registerListener(this);
|
||||||
|
classHolder =
|
||||||
|
NativeDetector.inNativeImage() ? frameworkModel.getBeanFactory().getBean(ClassHolder.class) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -120,7 +125,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
|
|
||||||
private Class<?> loadClass0(ClassLoader classLoader, String className) throws ClassNotFoundException {
|
private Class<?> loadClass0(ClassLoader classLoader, String className) throws ClassNotFoundException {
|
||||||
if (checkStatus == SerializeCheckStatus.DISABLE) {
|
if (checkStatus == SerializeCheckStatus.DISABLE) {
|
||||||
return ClassUtils.forName(className, classLoader);
|
return classForName(classLoader, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
long hash = MAGIC_HASH_CODE;
|
long hash = MAGIC_HASH_CODE;
|
||||||
|
|
@ -133,7 +138,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
hash *= MAGIC_PRIME;
|
hash *= MAGIC_PRIME;
|
||||||
|
|
||||||
if (Arrays.binarySearch(allowPrefixes, hash) >= 0) {
|
if (Arrays.binarySearch(allowPrefixes, hash) >= 0) {
|
||||||
return ClassUtils.forName(className, classLoader);
|
return classForName(classLoader, className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +195,7 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> clazz = ClassUtils.forName(className, classLoader);
|
Class<?> clazz = classForName(classLoader, className);
|
||||||
if (serializeSecurityManager.getWarnedClasses().add(className)) {
|
if (serializeSecurityManager.getWarnedClasses().add(className)) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
PROTOCOL_UNTRUSTED_SERIALIZE_CLASS,
|
PROTOCOL_UNTRUSTED_SERIALIZE_CLASS,
|
||||||
|
|
@ -204,6 +209,16 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Class<?> classForName(ClassLoader classLoader, String className) throws ClassNotFoundException {
|
||||||
|
if (classHolder != null) {
|
||||||
|
Class<?> aClass = classHolder.loadClass(className, classLoader);
|
||||||
|
if (aClass != null) {
|
||||||
|
return aClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ClassUtils.forName(className, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
public static DefaultSerializeClassChecker getInstance() {
|
public static DefaultSerializeClassChecker getInstance() {
|
||||||
return FrameworkModel.defaultModel().getBeanFactory().getBean(DefaultSerializeClassChecker.class);
|
return FrameworkModel.defaultModel().getBeanFactory().getBean(DefaultSerializeClassChecker.class);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,24 +16,91 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.utils;
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.logger.Level;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.log4j.FileAppender;
|
import org.apache.logging.log4j.core.LogEvent;
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||||
|
import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender;
|
||||||
|
import org.apache.logging.log4j.core.appender.FileAppender;
|
||||||
|
import org.apache.logging.log4j.core.config.Property;
|
||||||
|
import org.apache.logging.log4j.core.config.plugins.Plugin;
|
||||||
|
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
|
||||||
|
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
|
||||||
|
|
||||||
public class DubboAppender extends FileAppender {
|
@Plugin(name = "Dubbo", category = "Core", elementType = "appender")
|
||||||
|
public class DubboAppender extends AbstractAppender {
|
||||||
|
|
||||||
|
public static class Builder extends AbstractOutputStreamAppender.Builder<Builder>
|
||||||
|
implements org.apache.logging.log4j.core.util.Builder<DubboAppender> {
|
||||||
|
|
||||||
|
@PluginBuilderAttribute
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
@PluginBuilderAttribute
|
||||||
|
private boolean append = true;
|
||||||
|
|
||||||
|
@PluginBuilderAttribute
|
||||||
|
private boolean locking;
|
||||||
|
|
||||||
|
public Builder setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAppend(boolean append) {
|
||||||
|
this.append = append;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setLocking(boolean locking) {
|
||||||
|
this.locking = locking;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DubboAppender build() {
|
||||||
|
return new DubboAppender(getName(), buildFileAppender());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <B extends FileAppender.Builder<B>> FileAppender buildFileAppender() {
|
||||||
|
FileAppender.Builder<B> builder = FileAppender.newBuilder();
|
||||||
|
builder.setIgnoreExceptions(isIgnoreExceptions());
|
||||||
|
builder.setLayout(getLayout());
|
||||||
|
builder.setName(getName() + "-File");
|
||||||
|
builder.setConfiguration(getConfiguration());
|
||||||
|
builder.setBufferedIo(isBufferedIo());
|
||||||
|
builder.setBufferSize(getBufferSize());
|
||||||
|
builder.setImmediateFlush(isImmediateFlush());
|
||||||
|
builder.withFileName(fileName == null || fileName.isEmpty() ? DEFAULT_FILE_NAME : fileName);
|
||||||
|
builder.withAppend(append);
|
||||||
|
builder.withLocking(locking);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final String DEFAULT_FILE_NAME = "dubbo.log";
|
private static final String DEFAULT_FILE_NAME = "dubbo.log";
|
||||||
|
|
||||||
|
public static boolean available = false;
|
||||||
|
public static List<Log> logList = new ArrayList<>();
|
||||||
|
|
||||||
|
private final FileAppender fileAppender;
|
||||||
|
|
||||||
public DubboAppender() {
|
public DubboAppender() {
|
||||||
super();
|
this("Dubbo", null);
|
||||||
setFile(DEFAULT_FILE_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean available = false;
|
private DubboAppender(String name, FileAppender fileAppender) {
|
||||||
|
super(name, null, null, true, Property.EMPTY_ARRAY);
|
||||||
|
this.fileAppender = fileAppender;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Log> logList = new ArrayList<>();
|
@PluginBuilderFactory
|
||||||
|
public static Builder newBuilder() {
|
||||||
|
return new Builder().asBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
public static void doStart() {
|
public static void doStart() {
|
||||||
available = true;
|
available = true;
|
||||||
|
|
@ -48,20 +115,39 @@ public class DubboAppender extends FileAppender {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void append(LoggingEvent event) {
|
public void append(LogEvent event) {
|
||||||
super.append(event);
|
if (fileAppender != null) {
|
||||||
|
fileAppender.append(event);
|
||||||
|
}
|
||||||
if (available) {
|
if (available) {
|
||||||
Log temp = parseLog(event);
|
logList.add(parseLog(event));
|
||||||
logList.add(temp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Log parseLog(LoggingEvent event) {
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
fileAppender.initialize();
|
||||||
|
super.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
fileAppender.start();
|
||||||
|
super.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
super.stop();
|
||||||
|
fileAppender.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Log parseLog(LogEvent event) {
|
||||||
Log log = new Log();
|
Log log = new Log();
|
||||||
log.setLogName(event.getLogger().getName());
|
log.setLogName(event.getLoggerName());
|
||||||
log.setLogLevel(event.getLevel());
|
log.setLogLevel(Level.valueOf(event.getLevel().name()));
|
||||||
log.setLogThread(event.getThreadName());
|
log.setLogThread(event.getThreadName());
|
||||||
log.setLogMessage(event.getMessage().toString());
|
log.setLogMessage(event.getMessage().getFormattedMessage());
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ package org.apache.dubbo.common.utils;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.SystemProperty.SYSTEM_JAVA_VERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JRE version
|
* JRE version
|
||||||
*/
|
*/
|
||||||
|
|
@ -81,7 +83,7 @@ public enum JRE {
|
||||||
|
|
||||||
private static JRE getJre() {
|
private static JRE getJre() {
|
||||||
// get java version from system property
|
// get java version from system property
|
||||||
String version = System.getProperty("java.version");
|
String version = SystemPropertyConfigUtils.getSystemProperty(SYSTEM_JAVA_VERSION);
|
||||||
boolean isBlank = StringUtils.isBlank(version);
|
boolean isBlank = StringUtils.isBlank(version);
|
||||||
if (isBlank) {
|
if (isBlank) {
|
||||||
logger.debug("java.version is blank");
|
logger.debug("java.version is blank");
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ public class JVMUtil {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// default is 32, means only print up to 32 lines
|
// default is 32, means only print up to 32 lines
|
||||||
int jstackMaxLine = 32;
|
int jstackMaxLine = 32;
|
||||||
String jstackMaxLineStr = System.getProperty(CommonConstants.DUBBO_JSTACK_MAXLINE);
|
String jstackMaxLineStr =
|
||||||
|
SystemPropertyConfigUtils.getSystemProperty(CommonConstants.DubboProperty.DUBBO_JSTACK_MAXLINE);
|
||||||
if (StringUtils.isNotEmpty(jstackMaxLineStr)) {
|
if (StringUtils.isNotEmpty(jstackMaxLineStr)) {
|
||||||
try {
|
try {
|
||||||
jstackMaxLine = Integer.parseInt(jstackMaxLineStr);
|
jstackMaxLine = Integer.parseInt(jstackMaxLineStr);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class JsonCompatibilityUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JsonCompatibilityUtil.class);
|
||||||
|
|
||||||
|
private static final Set<String> unsupportedClasses = new HashSet<>(Arrays.asList(
|
||||||
|
"java.util.Optional",
|
||||||
|
"java.util.Calendar",
|
||||||
|
"java.util.Iterator",
|
||||||
|
"java.io.InputStream",
|
||||||
|
"java.io.OutputStream"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a Class can be serialized by JSON.
|
||||||
|
* @param clazz Incoming Class.
|
||||||
|
* @return If a Class can be serialized by JSON, return true;
|
||||||
|
* else return false.
|
||||||
|
*/
|
||||||
|
public static boolean checkClassCompatibility(Class<?> clazz) {
|
||||||
|
Method[] methods = clazz.getDeclaredMethods();
|
||||||
|
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
for (Method method : methods) {
|
||||||
|
result = checkMethodCompatibility(method);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a Method can be serialized by JSON.
|
||||||
|
* @param method Incoming Method.
|
||||||
|
* @return If a Method can be serialized by JSON, return true;
|
||||||
|
* else return false.
|
||||||
|
*/
|
||||||
|
public static boolean checkMethodCompatibility(Method method) {
|
||||||
|
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Type[] types = method.getGenericParameterTypes();
|
||||||
|
List<Type> typeList = new ArrayList<>(Arrays.asList(types));
|
||||||
|
Type returnType = method.getGenericReturnType();
|
||||||
|
typeList.add(returnType);
|
||||||
|
for (Type type : typeList) {
|
||||||
|
result = checkType(type);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get unsupported methods.
|
||||||
|
* @param clazz
|
||||||
|
* @return If there are unsupported methods, return them by List;
|
||||||
|
* else return null.
|
||||||
|
*/
|
||||||
|
public static List<String> getUnsupportedMethods(Class<?> clazz) {
|
||||||
|
ArrayList<String> unsupportedMethods = new ArrayList<>();
|
||||||
|
|
||||||
|
Method[] methods = clazz.getDeclaredMethods();
|
||||||
|
|
||||||
|
for (Method method : methods) {
|
||||||
|
if (!checkMethodCompatibility(method)) {
|
||||||
|
unsupportedMethods.add(method.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unsupportedMethods.size() > 0 ? unsupportedMethods : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a Type can be serialized by JSON.
|
||||||
|
* @param classType Incoming Type.
|
||||||
|
* @return If a Type can be serialized by JSON, return true;
|
||||||
|
* else return false.
|
||||||
|
*/
|
||||||
|
private static boolean checkType(Type classType) {
|
||||||
|
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (classType instanceof TypeVariable) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classType instanceof ParameterizedType) {
|
||||||
|
|
||||||
|
Type[] types = ((ParameterizedType) classType).getActualTypeArguments();
|
||||||
|
List<Type> typeList = new ArrayList<>(Arrays.asList(types));
|
||||||
|
classType = ((ParameterizedType) classType).getRawType();
|
||||||
|
typeList.add(classType);
|
||||||
|
for (Type type : typeList) {
|
||||||
|
result = checkType(type);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (classType instanceof GenericArrayType) {
|
||||||
|
Type componentType = ((GenericArrayType) classType).getGenericComponentType();
|
||||||
|
result = checkType(componentType);
|
||||||
|
return result;
|
||||||
|
} else if (classType instanceof Class<?>) {
|
||||||
|
Class<?> clazz = (Class<?>) classType;
|
||||||
|
|
||||||
|
String className = clazz.getName();
|
||||||
|
|
||||||
|
if (clazz.isArray()) {
|
||||||
|
Type componentType = clazz.getComponentType();
|
||||||
|
result = checkType(componentType);
|
||||||
|
return result;
|
||||||
|
} else if (clazz.isPrimitive()) {
|
||||||
|
// deal with case of basic byte
|
||||||
|
return !unsupportedClasses.contains(className);
|
||||||
|
} else if (className.startsWith("java") || className.startsWith("javax")) {
|
||||||
|
return !unsupportedClasses.contains(className);
|
||||||
|
} else {
|
||||||
|
// deal with case of interface
|
||||||
|
if (clazz.isInterface()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// deal with case of abstract
|
||||||
|
if (Modifier.isAbstract(clazz.getModifiers())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (clazz.isEnum()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// deal with case of record
|
||||||
|
// if (clazz.isRecord()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// deal with field one by one
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
Type type = field.getGenericType();
|
||||||
|
Class<?> fieldClass = field.getType();
|
||||||
|
result = checkType(type);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue