mirror of https://github.com/longtai-cn/hippo4j
Replaces the two hand-maintained READMEs (Chinese + English) with a single README.src.md, regenerated by nrg-maven-plugin during the compile phase. Both outputs are byte-identical to the originals (modulo a 2-line auto-generated header NRG injects at the top). The non-default English filename README-EN.md (with hyphen separator) is preserved through nrg.fileNamePattern.en. Chinese remains the default language so README.md continues to point to the Chinese version.pull/1619/head
parent
c734d00ec1
commit
de9d912448
@ -1,35 +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.
|
||||
#
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 0%
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
ignore:
|
||||
- "examples/.*"
|
||||
- "docs/.*"
|
||||
- "tests/.*"
|
||||
- "checkstyle/.*"
|
||||
- "format/.*"
|
||||
- "threadpool/console-new/.*"
|
||||
- "threadpool/console/.*"
|
||||
@ -1,3 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
custom: ['https://hippo4j.cn/community/sponsor']
|
||||
@ -1,112 +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.
|
||||
#
|
||||
|
||||
name: Bug report
|
||||
title: "[Bug] Bug title "
|
||||
description: If something isn't working as expected.
|
||||
labels: [ "type: bug" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For better global communication, Please write in English.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Search before asking
|
||||
description: >
|
||||
Please make sure to search in the [issues](https://github.com/opengoofy/hippo4j/issues)
|
||||
first to see whether the same issue was reported already.
|
||||
options:
|
||||
- label: >
|
||||
I had searched in the [issues](https://github.com/opengoofy/hippo4j/issues) and found
|
||||
no similar issues.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Describe the environment.
|
||||
options:
|
||||
- Mac
|
||||
- Windows
|
||||
- Linux
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Hippo4j version
|
||||
description: Describe the Hippo4j version.
|
||||
options:
|
||||
- develop
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What happened
|
||||
description: Describe what happened.
|
||||
placeholder: >
|
||||
A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: How to reproduce
|
||||
description: >
|
||||
Describe the steps to reproduce the bug here.
|
||||
placeholder: >
|
||||
Please make sure you provide a reproducible step-by-step case of how to reproduce the problem
|
||||
as minimally and precisely as possible.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Debug logs
|
||||
description: Anything else we need to know?
|
||||
placeholder: >
|
||||
Add your debug logs here.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit PR?
|
||||
description: >
|
||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
||||
especially if you already have a good understanding of how to implement the fix.
|
||||
options:
|
||||
- label: Yes I am willing to submit a PR!
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: >
|
||||
The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it..
|
||||
options:
|
||||
- label: I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) *
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Thanks for completing our form!"
|
||||
@ -1,68 +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.
|
||||
#
|
||||
|
||||
name: Documentation Related
|
||||
title: "[Doc] Documentation Related "
|
||||
description: I find some issues related to the documentation.
|
||||
labels: [ "type: documentation" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For better global communication, Please write in English.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Search before asking
|
||||
description: >
|
||||
Please make sure to search in the [issues](https://github.com/opengoofy/hippo4j/issues)
|
||||
first to see whether the same issue was reported already.
|
||||
options:
|
||||
- label: >
|
||||
I had searched in the [issues](https://github.com/opengoofy/hippo4j/issues) and found
|
||||
no similar issues.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Documentation Related
|
||||
description: Describe the suggestion about document.
|
||||
placeholder: >
|
||||
e.g There is a typo
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit PR?
|
||||
description: >
|
||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
||||
especially if you already have a good understanding of how to implement the fix.
|
||||
options:
|
||||
- label: Yes I am willing to submit a PR!
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: >
|
||||
The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it..
|
||||
options:
|
||||
- label: I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) *
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Thanks for completing our form!"
|
||||
@ -1,77 +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.
|
||||
#
|
||||
|
||||
name: Enhancement Request
|
||||
title: "[Enhancement] Enhancement title"
|
||||
description: I want to suggest an enhancement for this project
|
||||
labels: [ "type: enhancement" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For better global communication, Please write in English.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Search before asking
|
||||
description: >
|
||||
Please make sure to search in the [issues](https://github.com/opengoofy/hippo4j/issues)
|
||||
first to see whether the same issue was reported already.
|
||||
options:
|
||||
- label: >
|
||||
I had searched in the [issues](https://github.com/opengoofy/hippo4j/issues) and found
|
||||
no similar issues.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Enhancement Request
|
||||
description: Describe the suggestion.
|
||||
placeholder: >
|
||||
First of all: Have you checked the docs https://hippo4j.cn/community/dev_convention/code,
|
||||
or GitHub issues whether someone else has already reported your issue?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the solution you'd like
|
||||
description: Describe the suggestion.
|
||||
placeholder: >
|
||||
A clear and concise description of what you want to happen. Add any considered drawbacks.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit PR?
|
||||
description: >
|
||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
||||
especially if you already have a good understanding of how to implement the fix.
|
||||
options:
|
||||
- label: Yes I am willing to submit a PR!
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: >
|
||||
The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it..
|
||||
options:
|
||||
- label: I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) *
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Thanks for completing our form!"
|
||||
@ -1,70 +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.
|
||||
#
|
||||
|
||||
name: Feature Request
|
||||
title: "[Feature] Feature title "
|
||||
description: I want to suggest a feature for this project.
|
||||
labels: [ "type: feature" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For better global communication, Please write in English.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Search before asking
|
||||
description: >
|
||||
Please make sure to search in the [issues](https://github.com/opengoofy/hippo4j/issues)
|
||||
first to see whether the same issue was reported already.
|
||||
options:
|
||||
- label: >
|
||||
I had searched in the [issues](https://github.com/opengoofy/hippo4j/issues) and found
|
||||
no similar issues.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature Request
|
||||
description: Describe the feature.
|
||||
placeholder: >
|
||||
First of all: Have you checked the docs https://hippo4j.cn/community/dev_convention/code,
|
||||
or GitHub issues whether someone else has already reported your issue?
|
||||
Maybe the feature already exists?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit PR?
|
||||
description: >
|
||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
||||
especially if you already have a good understanding of how to implement the fix.
|
||||
options:
|
||||
- label: Yes I am willing to submit a PR!
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: >
|
||||
The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it..
|
||||
options:
|
||||
- label: I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) *
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Thanks for completing our form!"
|
||||
@ -1,51 +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.
|
||||
#
|
||||
|
||||
name: Question
|
||||
title: "[Question] Question title "
|
||||
description: I have a question that isn't answered in docs or issue.
|
||||
labels: [ "type: question" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For better global communication, Please write in English.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Search before asking
|
||||
description: >
|
||||
Please make sure to search in the [issues](https://github.com/opengoofy/hippo4j/issues)
|
||||
first to see whether the same issue was reported already.
|
||||
options:
|
||||
- label: >
|
||||
I had searched in the [issues](https://github.com/opengoofy/hippo4j/issues) and found
|
||||
no similar issues.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Question
|
||||
description: Describe your question.
|
||||
placeholder: >
|
||||
Describe your question here :D
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Thanks for completing our form!"
|
||||
@ -1,6 +0,0 @@
|
||||
Fixes #ISSUSE_ID
|
||||
|
||||
Changes proposed in this pull request:
|
||||
-
|
||||
|
||||
> Check mailbox configuration when submitting. [Contributor Guide](https://hippo4j.cn/community/contributor-guide)
|
||||
@ -1,6 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@ -1,89 +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.
|
||||
#
|
||||
|
||||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '**/pom.xml'
|
||||
- '**/src/main/**'
|
||||
- '**/src/test/**'
|
||||
- '!*.md'
|
||||
- '!docs/**'
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '**/pom.xml'
|
||||
- '**/src/main/**'
|
||||
- '**/src/test/**'
|
||||
- '!*.md'
|
||||
- '!docs/**'
|
||||
repository_dispatch:
|
||||
types: [rerun-ci]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
unix:
|
||||
name: JDK ${{ matrix.java.version }} - on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ macos-latest ]
|
||||
java:
|
||||
- {
|
||||
version: 11
|
||||
}
|
||||
- {
|
||||
version: 17
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build with Maven
|
||||
run: echo y | mvn clean install -Dskip.gpg=true -Dspotless.apply.skip=true -Dmaven.javadoc.skip=true
|
||||
|
||||
test-coverage:
|
||||
if: github.repository == 'opengoofy/hippo4j'
|
||||
name: Test coverage report
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache Maven Repos
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: hippo4j-maven-third-party-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
hippo4j-maven-third-party-
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Test with Maven
|
||||
run: echo y | mvn -T1C clean install -Dskip.gpg=true -Dspotless.apply.skip=true -Dskip.jacoco.plugin=false
|
||||
- name: Upload to Codecov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
@ -1,40 +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.
|
||||
#
|
||||
|
||||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
contrib-readme-job:
|
||||
runs-on: ubuntu-latest
|
||||
name: A job to automate contrib in readme
|
||||
steps:
|
||||
- name: Contribute List
|
||||
uses: akhilmhdh/contributors-readme-action@v2.3.6
|
||||
with:
|
||||
image_size: 50
|
||||
columns_per_row: 9
|
||||
committer_email: wechat202110@163.com
|
||||
committer_username: hippo4jbot[bot]
|
||||
commit_message: 'Update the list of contributors'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }}
|
||||
@ -1,56 +0,0 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
!**/node_modules/
|
||||
!**/dist/
|
||||
|
||||
### Agent ###
|
||||
hippo4j-agent/
|
||||
**/dependency-reduced-pom.xml
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
# .vscode/
|
||||
|
||||
# maven plugin ignore
|
||||
*.gpg
|
||||
.flattened-pom.xml
|
||||
|
||||
### Docs ###
|
||||
docs/node_modules
|
||||
docs/build
|
||||
docs/.docusaurus
|
||||
|
||||
|
||||
### Docker ###
|
||||
docker/conf
|
||||
docker/target
|
||||
|
||||
### OS ###
|
||||
.DS_Store
|
||||
@ -1 +0,0 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
|
||||
@ -1,41 +0,0 @@
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[less]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
}
|
||||
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (properties) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
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.
|
||||
@ -1,76 +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.
|
||||
|
||||
# The service name in UI
|
||||
# ${service name} = [${group name}::]${logic name}
|
||||
# The group name is optional only.
|
||||
agent.service_name=${HIPPO4J_AGENT_NAME:Your_ApplicationName}
|
||||
|
||||
# The agent namespace
|
||||
agent.namespace=${HIPPO4J_AGENT_NAMESPACE:}
|
||||
|
||||
# The agent cluster
|
||||
agent.cluster=${HIPPO4J_AGENT_CLUSTER:}
|
||||
|
||||
# If the operation name of the first span is included in this set, this segment should be ignored. Multiple values should be separated by `,`.
|
||||
agent.ignore_suffix=${HIPPO4J_AGENT_IGNORE_SUFFIX:.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg}
|
||||
|
||||
# If true, Hippo4j agent will save all instrumented classes files in `/debugging` folder.
|
||||
# SkyWalking team may ask for these files in order to resolve compatible problem.
|
||||
agent.is_open_debugging_class=${SW_AGENT_OPEN_DEBUG:false}
|
||||
|
||||
# If true, Hippo4j agent will cache all instrumented classes files to memory or disk files (decided by class cache mode),
|
||||
# allow other javaagent to enhance those classes that enhanced by SkyWalking agent.
|
||||
agent.is_cache_enhanced_class=${SW_AGENT_CACHE_CLASS:false}
|
||||
|
||||
# The instrumented classes cache mode: MEMORY or FILE
|
||||
# MEMORY: cache class bytes to memory, if instrumented classes is too many or too large, it may take up more memory
|
||||
# FILE: cache class bytes in `/class-cache` folder, automatically clean up cached class files when the application exits
|
||||
agent.class_cache_mode=${SW_AGENT_CLASS_CACHE_MODE:MEMORY}
|
||||
|
||||
# Logging level
|
||||
logging.level=${HIPPO4J_LOGGING_LEVEL:INFO}
|
||||
# Logging file_name
|
||||
logging.file_name=${HIPPO4J_LOGGING_FILE_NAME:hippo4j-api.log}
|
||||
# Log output. Default is FILE. Use CONSOLE means output to stdout.
|
||||
logging.output=${SW_LOGGING_OUTPUT:FILE}
|
||||
# Log files directory. Default is blank string, meaning use "{theHippo4jAgentJarDir}/logs " to output logs.
|
||||
# {theHippo4jAgentJarDir} is the directory where the hippo4j agent jar file is located
|
||||
logging.dir=${HIPPO4J_LOGGING_DIR:}
|
||||
# Logger resolver: PATTERN or JSON. The default is PATTERN, which uses logging.pattern to print traditional text logs.
|
||||
# JSON resolver prints logs in JSON format.
|
||||
logging.resolver=${HIPPO4J_LOGGING_RESOLVER:PATTERN}
|
||||
# Logging format. There are all conversion specifiers:
|
||||
# * %level means log level.
|
||||
# * %timestamp means now of time with format yyyy-MM-dd HH:mm:ss:SSS.
|
||||
# * %thread means name of current thread.
|
||||
# * %msg means some message which user logged.
|
||||
# * %class means SimpleName of TargetClass.
|
||||
# * %throwable means a throwable which user called.
|
||||
# * %agent_name means agent.service_name. Only apply to the PatternLogger.
|
||||
logging.pattern=${HIPPO4J_LOGGING_PATTERN:%level %timestamp %thread %class : %msg %throwable}
|
||||
# Logging max_file_size, default: 300 * 1024 * 1024 = 314572800
|
||||
logging.max_file_size=${HIPPO4J_LOGGING_MAX_FILE_SIZE:314572800}
|
||||
# The max history log files. When rollover happened, if log files exceed this number,
|
||||
# then the oldest file will be delete. Negative or zero means off, by default.
|
||||
logging.max_history_files=${HIPPO4J_LOGGING_MAX_HISTORY_FILES:-1}
|
||||
|
||||
# Mount the specific folders of the plugins. Plugins in mounted folders would work.
|
||||
plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations}
|
||||
# Peer maximum description limit.
|
||||
plugin.peer_max_length=${SW_PLUGIN_PEER_MAX_LENGTH:200}
|
||||
# Exclude some plugins define in plugins dir.Plugin names is defined in [Agent plugin list](Plugin-list.md)
|
||||
plugin.exclude_plugins=${SW_EXCLUDE_PLUGINS:}
|
||||
@ -1,232 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
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.
|
||||
|
||||
=======================================================================
|
||||
Apache SkyWalking Subcomponents:
|
||||
|
||||
The Apache SkyWalking project contains subcomponents with separate copyright
|
||||
notices and license terms. Your use of the source code for the these
|
||||
subcomponents is subject to the terms and conditions of the following
|
||||
licenses.
|
||||
|
||||
========================================================================
|
||||
Apache 2.0 licenses
|
||||
========================================================================
|
||||
|
||||
The following components are provided under the Apache License. See project link for details.
|
||||
The text of each license is the standard Apache 2.0 license.
|
||||
|
||||
raphw (byte-buddy) 1.12.13: http://bytebuddy.net/ , Apache 2.0
|
||||
Google: grpc-java 1.44.0: https://github.com/grpc/grpc-java, Apache 2.0
|
||||
Google: gson 2.8.9: https://github.com/google/gson , Apache 2.0
|
||||
Google: proto-google-common-protos 2.0.1: https://github.com/googleapis/googleapis , Apache 2.0
|
||||
Google: jsr305 3.0.2: http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.pom , Apache 2.0
|
||||
netty 4.1.79: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0
|
||||
|
||||
========================================================================
|
||||
BSD licenses
|
||||
========================================================================
|
||||
|
||||
The following components are provided under a BSD license. See project link for details.
|
||||
The text of each license is also included at licenses/LICENSE-[project].txt.
|
||||
|
||||
asm 9.2:https://gitlab.ow2.org , BSD-3-Clause
|
||||
@ -1,299 +0,0 @@
|
||||
Opengoofy Hippo4j
|
||||
Copyright 2017-2022 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
========================================================================
|
||||
|
||||
grpc-java NOTICE
|
||||
|
||||
========================================================================
|
||||
Copyright 2014, gRPC Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
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.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
This product contains a modified portion of 'OkHttp', an open source
|
||||
HTTP & SPDY client for Android and Java applications, which can be obtained
|
||||
at:
|
||||
|
||||
* LICENSE:
|
||||
* okhttp/third_party/okhttp/LICENSE (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/square/okhttp
|
||||
* LOCATION_IN_GRPC:
|
||||
* okhttp/third_party/okhttp
|
||||
|
||||
This product contains a modified portion of 'Netty', an open source
|
||||
networking library, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* netty/third_party/netty/LICENSE.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://netty.io
|
||||
* LOCATION_IN_GRPC:
|
||||
* netty/third_party/netty
|
||||
|
||||
========================================================================
|
||||
|
||||
grpc NOTICE
|
||||
|
||||
========================================================================
|
||||
|
||||
Copyright 2014 gRPC authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
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.
|
||||
|
||||
|
||||
========================================================================
|
||||
|
||||
netty NOTICE
|
||||
|
||||
========================================================================
|
||||
|
||||
|
||||
The Netty Project
|
||||
=================
|
||||
|
||||
Please visit the Netty web site for more information:
|
||||
|
||||
* http://netty.io/
|
||||
|
||||
Copyright 2014 The Netty Project
|
||||
|
||||
The Netty Project 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.
|
||||
|
||||
Also, please refer to each LICENSE.<component>.txt file, which is located in
|
||||
the 'license' directory of the distribution file, for the license terms of the
|
||||
components that this product depends on.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
This product contains the extensions to Java Collections Framework which has
|
||||
been derived from the works by JSR-166 EG, Doug Lea, and Jason T. Greene:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jsr166y.txt (Public Domain)
|
||||
* HOMEPAGE:
|
||||
* http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/
|
||||
* http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbosscache/experimental/jsr166/
|
||||
|
||||
This product contains a modified version of Robert Harder's Public Domain
|
||||
Base64 Encoder and Decoder, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.base64.txt (Public Domain)
|
||||
* HOMEPAGE:
|
||||
* http://iharder.sourceforge.net/current/java/base64/
|
||||
|
||||
This product contains a modified portion of 'Webbit', an event based
|
||||
WebSocket and HTTP server, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.webbit.txt (BSD License)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/joewalnes/webbit
|
||||
|
||||
This product contains a modified portion of 'SLF4J', a simple logging
|
||||
facade for Java, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.slf4j.txt (MIT License)
|
||||
* HOMEPAGE:
|
||||
* http://www.slf4j.org/
|
||||
|
||||
This product contains a modified portion of 'Apache Harmony', an open source
|
||||
Java SE, which can be obtained at:
|
||||
|
||||
* NOTICE:
|
||||
* license/NOTICE.harmony.txt
|
||||
* LICENSE:
|
||||
* license/LICENSE.harmony.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* http://archive.apache.org/dist/harmony/
|
||||
|
||||
This product contains a modified portion of 'jbzip2', a Java bzip2 compression
|
||||
and decompression library written by Matthew J. Francis. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jbzip2.txt (MIT License)
|
||||
* HOMEPAGE:
|
||||
* https://code.google.com/p/jbzip2/
|
||||
|
||||
This product contains a modified portion of 'libdivsufsort', a C API library to construct
|
||||
the suffix array and the Burrows-Wheeler transformed string for any input string of
|
||||
a constant-size alphabet written by Yuta Mori. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.libdivsufsort.txt (MIT License)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/y-256/libdivsufsort
|
||||
|
||||
This product contains a modified portion of Nitsan Wakart's 'JCTools', Java Concurrency Tools for the JVM,
|
||||
which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jctools.txt (ASL2 License)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/JCTools/JCTools
|
||||
|
||||
This product optionally depends on 'JZlib', a re-implementation of zlib in
|
||||
pure Java, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jzlib.txt (BSD style License)
|
||||
* HOMEPAGE:
|
||||
* http://www.jcraft.com/jzlib/
|
||||
|
||||
This product optionally depends on 'Compress-LZF', a Java library for encoding and
|
||||
decoding data in LZF format, written by Tatu Saloranta. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.compress-lzf.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/ning/compress
|
||||
|
||||
This product optionally depends on 'lz4', a LZ4 Java compression
|
||||
and decompression library written by Adrien Grand. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.lz4.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/jpountz/lz4-java
|
||||
|
||||
This product optionally depends on 'lzma-java', a LZMA Java compression
|
||||
and decompression library, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.lzma-java.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/jponge/lzma-java
|
||||
|
||||
This product contains a modified portion of 'jfastlz', a Java port of FastLZ compression
|
||||
and decompression library written by William Kinney. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jfastlz.txt (MIT License)
|
||||
* HOMEPAGE:
|
||||
* https://code.google.com/p/jfastlz/
|
||||
|
||||
This product contains a modified portion of and optionally depends on 'Protocol Buffers', Google's data
|
||||
interchange format, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.protobuf.txt (New BSD License)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/google/protobuf
|
||||
|
||||
This product optionally depends on 'Bouncy Castle Crypto APIs' to generate
|
||||
a temporary self-signed X.509 certificate when the JVM does not provide the
|
||||
equivalent functionality. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.bouncycastle.txt (MIT License)
|
||||
* HOMEPAGE:
|
||||
* http://www.bouncycastle.org/
|
||||
|
||||
This product optionally depends on 'Snappy', a compression library produced
|
||||
by Google Inc, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.snappy.txt (New BSD License)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/google/snappy
|
||||
|
||||
This product optionally depends on 'JBoss Marshalling', an alternative Java
|
||||
serialization API, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.jboss-marshalling.txt (GNU LGPL 2.1)
|
||||
* HOMEPAGE:
|
||||
* http://www.jboss.org/jbossmarshalling
|
||||
|
||||
This product optionally depends on 'Caliper', Google's micro-
|
||||
benchmarking framework, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.caliper.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/google/caliper
|
||||
|
||||
This product optionally depends on 'Apache Commons Logging', a logging
|
||||
framework, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.commons-logging.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* http://commons.apache.org/logging/
|
||||
|
||||
This product optionally depends on 'Apache Log4J', a logging framework, which
|
||||
can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.log4j.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* http://logging.apache.org/log4j/
|
||||
|
||||
This product optionally depends on 'Aalto XML', an ultra-high performance
|
||||
non-blocking XML processor, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.aalto-xml.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* http://wiki.fasterxml.com/AaltoHome
|
||||
|
||||
This product contains a modified version of 'HPACK', a Java implementation of
|
||||
the HTTP/2 HPACK algorithm written by Twitter. It can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.hpack.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/twitter/hpack
|
||||
|
||||
This product contains a modified portion of 'Apache Commons Lang', a Java library
|
||||
provides utilities for the java.lang API, which can be obtained at:
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.commons-lang.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://commons.apache.org/proper/commons-lang/
|
||||
|
||||
|
||||
This product contains the Maven wrapper scripts from 'Maven Wrapper', that provides an easy way to ensure a user has everything necessary to run the Maven build.
|
||||
|
||||
* LICENSE:
|
||||
* license/LICENSE.mvn-wrapper.txt (Apache License 2.0)
|
||||
* HOMEPAGE:
|
||||
* https://github.com/takari/maven-wrapper
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-agent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hippo4j-agent-bootstrap</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<premain.class>cn.hippo4j.agent.bootstrap.Hippo4jAgent</premain.class>
|
||||
<can.redefine.classes>true</can.redefine.classes>
|
||||
<can.retransform.classes>true</can.retransform.classes>
|
||||
<shade.net.bytebuddy.source>net.bytebuddy</shade.net.bytebuddy.source>
|
||||
<shade.net.bytebuddy.target>${shade.package}.${shade.net.bytebuddy.source}</shade.net.bytebuddy.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-agent-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>hippo4j-threadpool-agent</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<manifestEntries>
|
||||
<Premain-Class>${premain.class}</Premain-Class>
|
||||
<Can-Redefine-Classes>${can.redefine.classes}</Can-Redefine-Classes>
|
||||
<Can-Retransform-Classes>${can.retransform.classes}</Can-Retransform-Classes>
|
||||
</manifestEntries>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>*:gson</exclude>
|
||||
<exclude>io.grpc:*</exclude>
|
||||
<exclude>io.netty:*</exclude>
|
||||
<exclude>io.opencensus:*</exclude>
|
||||
<exclude>com.google.*:*</exclude>
|
||||
<exclude>com.google.guava:guava</exclude>
|
||||
<exclude>org.checkerframework:checker-compat-qual</exclude>
|
||||
<exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude>
|
||||
<exclude>io.perfmark:*</exclude>
|
||||
<exclude>org.slf4j:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>${shade.net.bytebuddy.source}</pattern>
|
||||
<shadedPattern>${shade.net.bytebuddy.target}</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>net.bytebuddy:byte-buddy</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/versions/9/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>clean</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<delete dir="${project.basedir}/../hippo4j-agent" />
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>package</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<mkdir dir="${project.basedir}/../hippo4j-agent" />
|
||||
<copy file="${project.build.directory}/hippo4j-threadpool-agent.jar" tofile="${project.basedir}/../hippo4j-agent/hippo4j-threadpool-agent.jar" overwrite="true" />
|
||||
<mkdir dir="${project.basedir}/../hippo4j-agent/config" />
|
||||
<mkdir dir="${project.basedir}/../hippo4j-agent/logs" />
|
||||
<copydir src="${project.basedir}/../config" dest="${project.basedir}/../hippo4j-agent/config" forceoverwrite="true" />
|
||||
<copydir src="${project.basedir}/../dist-material" dest="${project.basedir}/../hippo4j-agent" />
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -1,263 +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 cn.hippo4j.agent.bootstrap;
|
||||
|
||||
import cn.hippo4j.agent.core.boot.ServiceManager;
|
||||
import cn.hippo4j.agent.core.conf.SnifferConfigInitializer;
|
||||
import cn.hippo4j.agent.core.jvm.LoadedLibraryCollector;
|
||||
import cn.hippo4j.agent.core.plugin.AbstractClassEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.EnhanceContext;
|
||||
import cn.hippo4j.agent.core.plugin.InstrumentDebuggingClass;
|
||||
import cn.hippo4j.agent.core.plugin.PluginBootstrap;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.PluginFinder;
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.BootstrapInstrumentBoost;
|
||||
import cn.hippo4j.agent.core.plugin.bytebuddy.CacheableTransformerDecorator;
|
||||
import cn.hippo4j.agent.core.plugin.jdk9module.JDK9ModuleExporter;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
import cn.hippo4j.common.conf.Config;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.description.NamedElement;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.dynamic.scaffold.TypeValidation;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.bytebuddy.utility.JavaModule;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.nameContains;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* Hippo4j Agent
|
||||
*/
|
||||
public class Hippo4jAgent {
|
||||
|
||||
private static ILog LOGGER = LogManager.getLogger(Hippo4jAgent.class);
|
||||
|
||||
/**
|
||||
* Main entrance. Use byte-buddy transform to enhance all classes, which define in plugins.
|
||||
*/
|
||||
public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException {
|
||||
final PluginFinder pluginFinder;
|
||||
try {
|
||||
SnifferConfigInitializer.initializeCoreConfig(agentArgs);
|
||||
} catch (Exception e) {
|
||||
// try to resolve a new logger, and use the new logger to write the error log here
|
||||
LogManager.getLogger(Hippo4jAgent.class)
|
||||
.error(e, "Hippo4j agent initialized failure. Shutting down.");
|
||||
return;
|
||||
} finally {
|
||||
// refresh logger again after initialization finishes
|
||||
LOGGER = LogManager.getLogger(Hippo4jAgent.class);
|
||||
}
|
||||
|
||||
try {
|
||||
pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
|
||||
} catch (AgentPackageNotFoundException ape) {
|
||||
LOGGER.error(ape, "Locate agent.jar failure. Shutting down.");
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Hippo4j agent initialized failure. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));
|
||||
|
||||
AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
|
||||
nameStartsWith("net.bytebuddy.")
|
||||
.or(nameStartsWith("org.slf4j."))
|
||||
.or(nameStartsWith("org.groovy."))
|
||||
.or(nameContains("javassist"))
|
||||
.or(nameContains(".asm."))
|
||||
.or(nameContains(".reflectasm."))
|
||||
.or(nameStartsWith("sun.reflect"))
|
||||
.or(allHippo4jAgentExcludeToolkit())
|
||||
.or(ElementMatchers.isSynthetic()));
|
||||
|
||||
JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();
|
||||
try {
|
||||
agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Hippo4j agent inject bootstrap instrumentation failure. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Hippo4j agent open read edge in JDK 9+ failure. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config.Agent.IS_CACHE_ENHANCED_CLASS) {
|
||||
try {
|
||||
agentBuilder = agentBuilder.with(new CacheableTransformerDecorator(Config.Agent.CLASS_CACHE_MODE));
|
||||
LOGGER.info("Hippo4j agent class cache [{}] activated.", Config.Agent.CLASS_CACHE_MODE);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Hippo4j agent can't active class cache.");
|
||||
}
|
||||
}
|
||||
|
||||
agentBuilder.type(pluginFinder.buildMatch())
|
||||
.transform(new Transformer(pluginFinder))
|
||||
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
|
||||
.with(new RedefinitionListener())
|
||||
.with(new Listener())
|
||||
.installOn(instrumentation);
|
||||
|
||||
PluginFinder.pluginInitCompleted();
|
||||
|
||||
try {
|
||||
ServiceManager.INSTANCE.boot();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Hippo4j agent boot failure.");
|
||||
}
|
||||
|
||||
try {
|
||||
Class.forName("java.util.concurrent.ThreadPoolExecutor");
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOGGER.error(e, "Hippo4j agent boot failure.");
|
||||
}
|
||||
|
||||
Runtime.getRuntime()
|
||||
.addShutdownHook(new Thread(ServiceManager.INSTANCE::shutdown, "hippo4j service shutdown thread"));
|
||||
}
|
||||
|
||||
/**
|
||||
* transformer
|
||||
*/
|
||||
private static class Transformer implements AgentBuilder.Transformer {
|
||||
|
||||
private PluginFinder pluginFinder;
|
||||
|
||||
Transformer(PluginFinder pluginFinder) {
|
||||
this.pluginFinder = pluginFinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicType.Builder<?> transform(final DynamicType.Builder<?> builder,
|
||||
final TypeDescription typeDescription,
|
||||
final ClassLoader classLoader,
|
||||
final JavaModule javaModule,
|
||||
final ProtectionDomain protectionDomain) {
|
||||
LoadedLibraryCollector.registerURLClassLoader(classLoader);
|
||||
List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription);
|
||||
if (pluginDefines.size() > 0) {
|
||||
DynamicType.Builder<?> newBuilder = builder;
|
||||
EnhanceContext context = new EnhanceContext();
|
||||
for (AbstractClassEnhancePluginDefine define : pluginDefines) {
|
||||
DynamicType.Builder<?> possibleNewBuilder = define.define(
|
||||
typeDescription, newBuilder, classLoader, context);
|
||||
if (possibleNewBuilder != null) {
|
||||
newBuilder = possibleNewBuilder;
|
||||
}
|
||||
}
|
||||
if (context.isEnhanced()) {
|
||||
LOGGER.debug("Finish the prepare stage for {}.", typeDescription.getName());
|
||||
}
|
||||
|
||||
return newBuilder;
|
||||
}
|
||||
|
||||
LOGGER.debug("Matched class {}, but ignore by finding mechanism.", typeDescription.getTypeName());
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
private static ElementMatcher.Junction<NamedElement> allHippo4jAgentExcludeToolkit() {
|
||||
return nameStartsWith("cn.hippo4j").and(not(nameStartsWith("cn.hippo4j.agent.toolkit.")));
|
||||
}
|
||||
|
||||
/**
|
||||
* listener
|
||||
*/
|
||||
private static class Listener implements AgentBuilder.Listener {
|
||||
|
||||
@Override
|
||||
public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformation(final TypeDescription typeDescription,
|
||||
final ClassLoader classLoader,
|
||||
final JavaModule module,
|
||||
final boolean loaded,
|
||||
final DynamicType dynamicType) {
|
||||
if (LOGGER.isDebugEnable()) {
|
||||
LOGGER.debug("On Transformation class {}.", typeDescription.getName());
|
||||
}
|
||||
|
||||
InstrumentDebuggingClass.INSTANCE.log(dynamicType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIgnored(final TypeDescription typeDescription,
|
||||
final ClassLoader classLoader,
|
||||
final JavaModule module,
|
||||
final boolean loaded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String typeName,
|
||||
final ClassLoader classLoader,
|
||||
final JavaModule module,
|
||||
final boolean loaded,
|
||||
final Throwable throwable) {
|
||||
LOGGER.error("Enhance class " + typeName + " error.", throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* redefinition listener
|
||||
*/
|
||||
private static class RedefinitionListener implements AgentBuilder.RedefinitionStrategy.Listener {
|
||||
|
||||
@Override
|
||||
public void onBatch(int index, List<Class<?>> batch, List<Class<?>> types) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends List<Class<?>>> onError(int index, List<Class<?>> batch, Throwable throwable, List<Class<?>> types) {
|
||||
LOGGER.error(throwable, "index={}, batch={}, types={}", index, batch, types);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(int amount, List<Class<?>> types, Map<List<Class<?>>, Throwable> failures) {
|
||||
/* do nothing */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,175 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-agent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hippo4j-agent-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<netty-tcnative-boringssl-static.version>2.0.7.Final</netty-tcnative-boringssl-static.version>
|
||||
<os-maven-plugin.version>1.4.1.Final</os-maven-plugin.version>
|
||||
<shade.com.google.source>com.google</shade.com.google.source>
|
||||
<shade.com.google.target>${shade.package}.${shade.com.google.source}</shade.com.google.target>
|
||||
<shade.io.grpc.source>io.grpc</shade.io.grpc.source>
|
||||
<shade.io.grpc.target>${shade.package}.${shade.io.grpc.source}</shade.io.grpc.target>
|
||||
<shade.io.netty.source>io.netty</shade.io.netty.source>
|
||||
<shade.io.netty.target>${shade.package}.${shade.io.netty.source}</shade.io.netty.target>
|
||||
<shade.io.opencensus.source>io.opencensus</shade.io.opencensus.source>
|
||||
<shade.io.opencensus.target>${shade.package}.${shade.io.opencensus.source}</shade.io.opencensus.target>
|
||||
<shade.io.perfmark.source>io.perfmark</shade.io.perfmark.source>
|
||||
<shade.io.perfmark.target>${shade.package}.${shade.io.perfmark.source}</shade.io.perfmark.target>
|
||||
<shade.org.slf4j.source>org.slf4j</shade.org.slf4j.source>
|
||||
<shade.org.slf4j.target>${shade.package}.${shade.org.slf4j.source}</shade.org.slf4j.target>
|
||||
<ststem-rules.version>1.18.0</ststem-rules.version>
|
||||
<jaxb.version>2.3.1</jaxb.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy-agent</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-threadpool-infra-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!--To fix https://github.com/DozerMapper/dozer/issues/865 -->
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>${jaxb.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
<version>${jaxb.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>${os-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>initialize</phase>
|
||||
<goals>
|
||||
<goal>detect</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>net.bytebuddy:byte-buddy:jar:</exclude>
|
||||
<exclude>com.google.errorprone:error_prone_annotations:jar:</exclude>
|
||||
<exclude>com.google.code.findbugs:jsr305:jar:</exclude>
|
||||
<exclude>com.google.android:annotations:jar:</exclude>
|
||||
<exclude>com.google.api.grpc:proto-google-common-protos:jar:</exclude>
|
||||
<exclude>org.checkerframework:checker-compat-qual:jar:</exclude>
|
||||
<exclude>org.codehaus.mojo:animal-sniffer-annotations:jar:</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>${shade.com.google.source}</pattern>
|
||||
<shadedPattern>${shade.com.google.target}</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>${shade.io.grpc.source}</pattern>
|
||||
<shadedPattern>${shade.io.grpc.target}</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>${shade.io.netty.source}</pattern>
|
||||
<shadedPattern>${shade.io.netty.target}</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>${shade.io.opencensus.source}</pattern>
|
||||
<shadedPattern>${shade.io.opencensus.target}</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>${shade.io.perfmark.source}</pattern>
|
||||
<shadedPattern>${shade.io.perfmark.target}</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>${shade.org.slf4j.source}</pattern>
|
||||
<shadedPattern>${shade.org.slf4j.target}</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>com.google.protobuf:protobuf-java</artifact>
|
||||
<excludes>
|
||||
<exclude>google/protobuf/*.proto</exclude>
|
||||
<exclude>google/protobuf/compiler/*.proto</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.base64;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* A wrapper of {@link java.util.Base64} with convenient conversion methods between {@code byte[]} and {@code String}
|
||||
*/
|
||||
public final class Base64 {
|
||||
|
||||
private static final java.util.Base64.Decoder DECODER = java.util.Base64.getDecoder();
|
||||
private static final java.util.Base64.Encoder ENCODER = java.util.Base64.getEncoder();
|
||||
|
||||
private Base64() {
|
||||
}
|
||||
|
||||
public static String decode2UTFString(String in) {
|
||||
return new String(DECODER.decode(in), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static String encode(String text) {
|
||||
return ENCODER.encodeToString(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,86 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* AgentPackagePath is a flag and finder to locate the Hippo4j agent.jar. It gets the absolute path of the agent jar.
|
||||
* The path is the required metadata for agent core looking up the plugins and toolkit activations. If the lookup
|
||||
* mechanism fails, the agent will exit directly.
|
||||
*/
|
||||
public class AgentPackagePath {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(AgentPackagePath.class);
|
||||
|
||||
private static File AGENT_PACKAGE_PATH;
|
||||
|
||||
public static File getPath() throws AgentPackageNotFoundException {
|
||||
if (AGENT_PACKAGE_PATH == null) {
|
||||
AGENT_PACKAGE_PATH = findPath();
|
||||
}
|
||||
return AGENT_PACKAGE_PATH;
|
||||
}
|
||||
|
||||
public static boolean isPathFound() {
|
||||
return AGENT_PACKAGE_PATH != null;
|
||||
}
|
||||
|
||||
private static File findPath() throws AgentPackageNotFoundException {
|
||||
String classResourcePath = AgentPackagePath.class.getName().replaceAll("\\.", "/") + ".class";
|
||||
|
||||
URL resource = ClassLoader.getSystemClassLoader().getResource(classResourcePath);
|
||||
if (resource != null) {
|
||||
String urlString = resource.toString();
|
||||
|
||||
LOGGER.debug("The beacon class location is {}.", urlString);
|
||||
|
||||
int insidePathIndex = urlString.indexOf('!');
|
||||
boolean isInJar = insidePathIndex > -1;
|
||||
|
||||
if (isInJar) {
|
||||
urlString = urlString.substring(urlString.indexOf("file:"), insidePathIndex);
|
||||
File agentJarFile = null;
|
||||
try {
|
||||
agentJarFile = new File(new URL(urlString).toURI());
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
LOGGER.error(e, "Can not locate agent jar file by url:" + urlString);
|
||||
}
|
||||
if (agentJarFile.exists()) {
|
||||
return agentJarFile.getParentFile();
|
||||
}
|
||||
} else {
|
||||
int prefixLength = "file:".length();
|
||||
String classLocation = urlString.substring(
|
||||
prefixLength, urlString.length() - classResourcePath.length());
|
||||
return new File(classLocation);
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.error("Can not locate agent jar file.");
|
||||
throw new AgentPackageNotFoundException("Can not locate agent jar file.");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,42 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
/**
|
||||
* The <code>BootService</code> is an interface to all remote, which need to boot when plugin mechanism begins to work.
|
||||
* {@link #boot()} will be called when <code>BootService</code> start up.
|
||||
*/
|
||||
public interface BootService {
|
||||
|
||||
void prepare() throws Throwable;
|
||||
|
||||
void boot() throws Throwable;
|
||||
|
||||
void onComplete() throws Throwable;
|
||||
|
||||
void shutdown() throws Throwable;
|
||||
|
||||
/**
|
||||
* {@code BootService}s with higher priorities will be started earlier, and shut down later than those {@code BootService}s with lower priorities.
|
||||
*
|
||||
* @return the priority of this {@code BootService}.
|
||||
*/
|
||||
default int priority() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1,28 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface DefaultImplementor {
|
||||
}
|
||||
@ -1,30 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface OverrideImplementor {
|
||||
|
||||
Class<? extends BootService> value();
|
||||
}
|
||||
@ -1,39 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* ConfigInitializationService provides the config class which should host all parameters originally from agent setup.
|
||||
* {@link cn.hippo4j.agent.core.conf.Config} provides the core level config, all plugins could implement
|
||||
* this interface to have the same capability about initializing config from agent.config, system properties and system
|
||||
* environment variables.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PluginConfig {
|
||||
|
||||
/**
|
||||
* @return Class as the root to do config initialization.
|
||||
*/
|
||||
Class<?> root();
|
||||
}
|
||||
@ -1,25 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
public class ServiceConflictException extends RuntimeException {
|
||||
|
||||
public ServiceConflictException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -1,149 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.loader.AgentClassLoader;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* The <code>ServiceManager</code> bases on {@link ServiceLoader}, load all {@link BootService} implementations.
|
||||
*/
|
||||
public enum ServiceManager {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(ServiceManager.class);
|
||||
private Map<Class, BootService> bootedServices = Collections.emptyMap();
|
||||
|
||||
public void boot() {
|
||||
bootedServices = loadAllServices();
|
||||
|
||||
prepare();
|
||||
startup();
|
||||
onComplete();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority).reversed()).forEach(service -> {
|
||||
try {
|
||||
service.shutdown();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error(e, "ServiceManager try to shutdown [{}] fail.", service.getClass().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Map<Class, BootService> loadAllServices() {
|
||||
Map<Class, BootService> bootedServices = new LinkedHashMap<>();
|
||||
List<BootService> allServices = new LinkedList<>();
|
||||
load(allServices);
|
||||
for (final BootService bootService : allServices) {
|
||||
Class<? extends BootService> bootServiceClass = bootService.getClass();
|
||||
boolean isDefaultImplementor = bootServiceClass.isAnnotationPresent(DefaultImplementor.class);
|
||||
if (isDefaultImplementor) {
|
||||
if (!bootedServices.containsKey(bootServiceClass)) {
|
||||
bootedServices.put(bootServiceClass, bootService);
|
||||
} else {
|
||||
// ignore the default service
|
||||
}
|
||||
} else {
|
||||
OverrideImplementor overrideImplementor = bootServiceClass.getAnnotation(OverrideImplementor.class);
|
||||
if (overrideImplementor == null) {
|
||||
if (!bootedServices.containsKey(bootServiceClass)) {
|
||||
bootedServices.put(bootServiceClass, bootService);
|
||||
} else {
|
||||
throw new ServiceConflictException("Duplicate service define for :" + bootServiceClass);
|
||||
}
|
||||
} else {
|
||||
Class<? extends BootService> targetService = overrideImplementor.value();
|
||||
if (bootedServices.containsKey(targetService)) {
|
||||
boolean presentDefault = bootedServices.get(targetService)
|
||||
.getClass()
|
||||
.isAnnotationPresent(DefaultImplementor.class);
|
||||
if (presentDefault) {
|
||||
bootedServices.put(targetService, bootService);
|
||||
} else {
|
||||
throw new ServiceConflictException(
|
||||
"Service " + bootServiceClass + " overrides conflict, " + "exist more than one service want to override :" + targetService);
|
||||
}
|
||||
} else {
|
||||
bootedServices.put(targetService, bootService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return bootedServices;
|
||||
}
|
||||
|
||||
private void prepare() {
|
||||
bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> {
|
||||
try {
|
||||
service.prepare();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error(e, "ServiceManager try to pre-start [{}] fail.", service.getClass().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startup() {
|
||||
bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> {
|
||||
try {
|
||||
service.boot();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error(e, "ServiceManager try to start [{}] fail.", service.getClass().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onComplete() {
|
||||
for (BootService service : bootedServices.values()) {
|
||||
try {
|
||||
service.onComplete();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error(e, "Service [{}] AfterBoot process fails.", service.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a {@link BootService} implementation, which is already started.
|
||||
*
|
||||
* @param serviceClass class name.
|
||||
* @param <T> {@link BootService} implementation class.
|
||||
* @return {@link BootService} instance
|
||||
*/
|
||||
public <T extends BootService> T findService(Class<T> serviceClass) {
|
||||
return (T) bootedServices.get(serviceClass);
|
||||
}
|
||||
|
||||
void load(List<BootService> allServices) {
|
||||
for (final BootService bootService : ServiceLoader.load(BootService.class, AgentClassLoader.getDefault())) {
|
||||
allServices.add(bootService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,87 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.util.ConfigInitializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
public class SpringBootConfigInitializer {
|
||||
|
||||
private static final ILog LOG = LogManager.getLogger(SpringBootConfigInitializer.class);
|
||||
|
||||
private static final Set<Class<?>> SPRING_BOOT_CONFIG_LIST = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
private static final long MAX_CACHE_TIME = 30L * 60L * 1000L; // half an hour.
|
||||
|
||||
private static final int MAX_CACHE_SIZE = 1000;
|
||||
|
||||
private static long PROPERTIES_LOAD_TIME;
|
||||
|
||||
public static Properties SPRING_PROPERTIES = null;
|
||||
|
||||
private SpringBootConfigInitializer() {
|
||||
|
||||
}
|
||||
|
||||
public static boolean isSpringPropertiesEmpty() {
|
||||
return SPRING_PROPERTIES == null || SPRING_PROPERTIES.isEmpty();
|
||||
}
|
||||
|
||||
public static synchronized void initializeConfig(SpringBootConfigNode springBootConfig) {
|
||||
if (SPRING_PROPERTIES != null) {
|
||||
try {
|
||||
LOG.info("initialize Spring Config Class {}.", springBootConfig.root());
|
||||
ConfigInitializer.initialize(SPRING_PROPERTIES, springBootConfig.root(), true);
|
||||
} catch (Throwable e) {
|
||||
LOG.error(e, "Failed to set the agent settings {} to Config={} ", SPRING_PROPERTIES, springBootConfig.root());
|
||||
}
|
||||
}
|
||||
boolean isStarting = PROPERTIES_LOAD_TIME == 0L;
|
||||
boolean overtime = System.currentTimeMillis() - PROPERTIES_LOAD_TIME > MAX_CACHE_TIME;
|
||||
boolean oversize = SPRING_BOOT_CONFIG_LIST.size() > MAX_CACHE_SIZE;
|
||||
// avoid memory leak.
|
||||
if (isStarting || (!oversize && !overtime)) {
|
||||
SPRING_BOOT_CONFIG_LIST.add(springBootConfig.root());
|
||||
} else {
|
||||
LOG.warn("spirng Config Class is skipped {}.", springBootConfig.root());
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void setSpringProperties(Properties properties) {
|
||||
if (properties != null && (SPRING_PROPERTIES == null || properties.size() > SPRING_PROPERTIES.size())) {
|
||||
LOG.info("set Spring Config Properties before : {}.", SPRING_PROPERTIES);
|
||||
SPRING_PROPERTIES = properties;
|
||||
LOG.info("set Spring Config Properties after : {}.", SPRING_PROPERTIES);
|
||||
PROPERTIES_LOAD_TIME = System.currentTimeMillis();
|
||||
}
|
||||
for (Class<?> clazz : SPRING_BOOT_CONFIG_LIST) {
|
||||
try {
|
||||
LOG.info("initialize Spring Config Class in loop {}.", clazz);
|
||||
ConfigInitializer.initialize(SPRING_PROPERTIES, clazz);
|
||||
} catch (Throwable e) {
|
||||
LOG.error(e, "Failed to set the agent Config={} from settings {}", clazz, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,33 +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 cn.hippo4j.agent.core.boot;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SpringBootConfigNode {
|
||||
|
||||
/**
|
||||
* @return Class as the root to do config initialization.
|
||||
*/
|
||||
Class<?> root();
|
||||
}
|
||||
@ -1,39 +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 cn.hippo4j.agent.core.conf;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static String PATH_SEPARATOR = System.getProperty("file.separator", "/");
|
||||
|
||||
public static String LINE_SEPARATOR = System.getProperty("line.separator", "\n");
|
||||
|
||||
public static String EMPTY_STRING = "";
|
||||
|
||||
public static char SERVICE_NAME_PART_CONNECTOR = '|';
|
||||
|
||||
// The name of the layer that represents agent-installed services,
|
||||
// which is defined at
|
||||
// https://github.com/apache/skywalking/blob/85ce1645be53e46286f36c0ea206c60db2d1a716/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/Layer.java#L30
|
||||
public static String EVENT_LAYER_NAME = "GENERAL";
|
||||
|
||||
public static int NULL_VALUE = 0;
|
||||
|
||||
public static String SPRING_BOOT_CONFIG_PREFIX = "spring.dynamic.thread-pool";
|
||||
|
||||
}
|
||||
@ -1,236 +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 cn.hippo4j.agent.core.conf;
|
||||
|
||||
import cn.hippo4j.agent.core.boot.AgentPackagePath;
|
||||
import cn.hippo4j.agent.core.util.PropertyPlaceholderHelper;
|
||||
import cn.hippo4j.agent.core.util.StringUtil;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
import cn.hippo4j.common.conf.Config;
|
||||
import cn.hippo4j.common.conf.ConfigNotFoundException;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.common.logging.core.JsonLogResolver;
|
||||
import cn.hippo4j.common.logging.core.PatternLogResolver;
|
||||
import cn.hippo4j.common.toolkit.agent.ConfigInitializer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static cn.hippo4j.common.conf.Constants.SERVICE_NAME_PART_CONNECTOR;
|
||||
|
||||
/**
|
||||
* The <code>SnifferConfigInitializer</code> initializes all configs in several way.
|
||||
*/
|
||||
public class SnifferConfigInitializer {
|
||||
|
||||
private static ILog LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
|
||||
private static final String SPECIFIED_CONFIG_PATH = "hippo4j_config";
|
||||
private static final String DEFAULT_CONFIG_FILE_NAME = "/config/agent.config";
|
||||
private static final String ENV_KEY_PREFIX = "hippo4j.";
|
||||
private static Properties AGENT_SETTINGS;
|
||||
private static boolean IS_INIT_COMPLETED = false;
|
||||
|
||||
/**
|
||||
* If the specified agent config path is set, the agent will try to locate the specified agent config. If the
|
||||
* specified agent config path is not set , the agent will try to locate `agent.config`, which should be in the
|
||||
* /config directory of agent package.
|
||||
* <p>
|
||||
* Also try to override the config by system.properties. All the keys in this place should start with {@link
|
||||
* #ENV_KEY_PREFIX}. e.g. in env `hippo4j.agent.service_name=yourAppName` to override `agent.service_name` in
|
||||
* config file.
|
||||
* <p>
|
||||
* At the end, `agent.service_name` and `collector.servers` must not be blank.
|
||||
*/
|
||||
public static void initializeCoreConfig(String agentOptions) {
|
||||
AGENT_SETTINGS = new Properties();
|
||||
try (final InputStreamReader configFileStream = loadConfig()) {
|
||||
AGENT_SETTINGS.load(configFileStream);
|
||||
for (String key : AGENT_SETTINGS.stringPropertyNames()) {
|
||||
String value = (String) AGENT_SETTINGS.get(key);
|
||||
AGENT_SETTINGS.put(key, PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(value, AGENT_SETTINGS));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Failed to read the config file, hippo4j is going to run in default config.");
|
||||
}
|
||||
|
||||
try {
|
||||
overrideConfigBySystemProp();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Failed to read the system properties.");
|
||||
}
|
||||
|
||||
agentOptions = StringUtil.trim(agentOptions, ',');
|
||||
if (!StringUtil.isEmpty(agentOptions)) {
|
||||
try {
|
||||
agentOptions = agentOptions.trim();
|
||||
LOGGER.info("Agent options is {}.", agentOptions);
|
||||
|
||||
overrideConfigByAgentOptions(agentOptions);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e, "Failed to parse the agent options, val is {}.", agentOptions);
|
||||
}
|
||||
}
|
||||
|
||||
initializeConfig(Config.class);
|
||||
// reconfigure logger after config initialization
|
||||
configureLogger();
|
||||
LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
|
||||
|
||||
if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {
|
||||
throw new ExceptionInInitializerError("`agent.service_name` is missing.");
|
||||
} else {
|
||||
if (StringUtil.isNotEmpty(Config.Agent.NAMESPACE) || StringUtil.isNotEmpty(Config.Agent.CLUSTER)) {
|
||||
Config.Agent.SERVICE_NAME = StringUtil.join(
|
||||
SERVICE_NAME_PART_CONNECTOR,
|
||||
Config.Agent.SERVICE_NAME,
|
||||
Config.Agent.NAMESPACE,
|
||||
Config.Agent.CLUSTER);
|
||||
}
|
||||
}
|
||||
// if (StringUtil.isEmpty(Config.Collector.BACKEND_SERVICE)) {
|
||||
// throw new ExceptionInInitializerError("`collector.backend_service` is missing.");
|
||||
// }
|
||||
if (Config.Plugin.PEER_MAX_LENGTH <= 3) {
|
||||
LOGGER.warn(
|
||||
"PEER_MAX_LENGTH configuration:{} error, the default value of 200 will be used.",
|
||||
Config.Plugin.PEER_MAX_LENGTH);
|
||||
Config.Plugin.PEER_MAX_LENGTH = 200;
|
||||
}
|
||||
|
||||
IS_INIT_COMPLETED = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize field values of any given config class.
|
||||
*
|
||||
* @param configClass to host the settings for code access.
|
||||
*/
|
||||
public static void initializeConfig(Class configClass) {
|
||||
if (AGENT_SETTINGS == null) {
|
||||
LOGGER.error("Plugin configs have to be initialized after core config initialization.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ConfigInitializer.initialize(AGENT_SETTINGS, configClass);
|
||||
} catch (IllegalAccessException e) {
|
||||
LOGGER.error(e,
|
||||
"Failed to set the agent settings {}"
|
||||
+ " to Config={} ",
|
||||
AGENT_SETTINGS, configClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static void overrideConfigByAgentOptions(String agentOptions) throws IllegalArgumentException {
|
||||
for (List<String> terms : parseAgentOptions(agentOptions)) {
|
||||
if (terms.size() != 2) {
|
||||
throw new IllegalArgumentException("[" + terms + "] is not a key-value pair.");
|
||||
}
|
||||
AGENT_SETTINGS.put(terms.get(0), terms.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<List<String>> parseAgentOptions(String agentOptions) {
|
||||
List<List<String>> options = new ArrayList<>();
|
||||
List<String> terms = new ArrayList<>();
|
||||
boolean isInQuotes = false;
|
||||
StringBuilder currentTerm = new StringBuilder();
|
||||
for (char c : agentOptions.toCharArray()) {
|
||||
if (c == '\'' || c == '"') {
|
||||
isInQuotes = !isInQuotes;
|
||||
} else if (c == '=' && !isInQuotes) { // key-value pair uses '=' as separator
|
||||
terms.add(currentTerm.toString());
|
||||
currentTerm = new StringBuilder();
|
||||
} else if (c == ',' && !isInQuotes) { // multiple options use ',' as separator
|
||||
terms.add(currentTerm.toString());
|
||||
currentTerm = new StringBuilder();
|
||||
|
||||
options.add(terms);
|
||||
terms = new ArrayList<>();
|
||||
} else {
|
||||
currentTerm.append(c);
|
||||
}
|
||||
}
|
||||
// add the last term and option without separator
|
||||
terms.add(currentTerm.toString());
|
||||
options.add(terms);
|
||||
return options;
|
||||
}
|
||||
|
||||
public static boolean isInitCompleted() {
|
||||
return IS_INIT_COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the config by system properties. The property key must start with `hippo4j`, the result should be as
|
||||
* same as in `agent.config`
|
||||
* <p>
|
||||
* such as: Property key of `agent.service_name` should be `hippo4j.agent.service_name`
|
||||
*/
|
||||
private static void overrideConfigBySystemProp() {
|
||||
Properties systemProperties = System.getProperties();
|
||||
for (final Map.Entry<Object, Object> prop : systemProperties.entrySet()) {
|
||||
String key = prop.getKey().toString();
|
||||
if (key.startsWith(ENV_KEY_PREFIX)) {
|
||||
String realKey = key.substring(ENV_KEY_PREFIX.length());
|
||||
AGENT_SETTINGS.put(realKey, prop.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the specified config file or default config file
|
||||
*
|
||||
* @return the config file {@link InputStream}, or null if not needEnhance.
|
||||
*/
|
||||
private static InputStreamReader loadConfig() throws AgentPackageNotFoundException, cn.hippo4j.common.conf.ConfigNotFoundException {
|
||||
String specifiedConfigPath = System.getProperty(SPECIFIED_CONFIG_PATH);
|
||||
File configFile = StringUtil.isEmpty(specifiedConfigPath) ? new File(
|
||||
AgentPackagePath.getPath(), DEFAULT_CONFIG_FILE_NAME) : new File(specifiedConfigPath);
|
||||
|
||||
if (configFile.exists() && configFile.isFile()) {
|
||||
try {
|
||||
LOGGER.info("Config file found in {}.", configFile);
|
||||
|
||||
return new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new ConfigNotFoundException("Failed to load agent.config", e);
|
||||
}
|
||||
}
|
||||
throw new ConfigNotFoundException("Failed to load agent.config.");
|
||||
}
|
||||
|
||||
static void configureLogger() {
|
||||
switch (Config.Logging.RESOLVER) {
|
||||
case JSON:
|
||||
LogManager.setLogResolver(new JsonLogResolver());
|
||||
break;
|
||||
case PATTERN:
|
||||
default:
|
||||
LogManager.setLogResolver(new PatternLogResolver());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,63 +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 cn.hippo4j.agent.core.conf.dynamic;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
public abstract class AgentConfigChangeWatcher {
|
||||
|
||||
// Config key, should match KEY in the Table of Agent Configuration Properties.
|
||||
private final String propertyKey;
|
||||
|
||||
public AgentConfigChangeWatcher(String propertyKey) {
|
||||
this.propertyKey = propertyKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the watcher, the new value received.
|
||||
*
|
||||
* @param value of new.
|
||||
*/
|
||||
public abstract void notify(ConfigChangeEvent value);
|
||||
|
||||
/**
|
||||
* @return current value of current config.
|
||||
*/
|
||||
public abstract String value();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AgentConfigChangeWatcher{"
|
||||
+ "propertyKey='" + propertyKey + '\''
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public static class ConfigChangeEvent {
|
||||
|
||||
private final String newValue;
|
||||
private final EventType eventType;
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
ADD, MODIFY, DELETE
|
||||
}
|
||||
}
|
||||
@ -1,132 +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 cn.hippo4j.agent.core.jvm;
|
||||
|
||||
import cn.hippo4j.agent.core.util.CollectionUtil;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class LoadedLibraryCollector {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(LoadedLibraryCollector.class);
|
||||
private static final String JAR_SEPARATOR = "!";
|
||||
private static Set<ClassLoader> CURRENT_URL_CLASSLOADER_SET = new HashSet<>();
|
||||
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
|
||||
/**
|
||||
* Prevent OOM in special scenes
|
||||
*/
|
||||
private static int CURRENT_URL_CLASSLOADER_SET_MAX_SIZE = 50;
|
||||
|
||||
public static void registerURLClassLoader(ClassLoader classLoader) {
|
||||
if (CURRENT_URL_CLASSLOADER_SET.size() < CURRENT_URL_CLASSLOADER_SET_MAX_SIZE && classLoader instanceof URLClassLoader) {
|
||||
CURRENT_URL_CLASSLOADER_SET.add(classLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getVmStartTime() {
|
||||
long startTime = ManagementFactory.getRuntimeMXBean().getStartTime();
|
||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(startTime));
|
||||
}
|
||||
|
||||
private static List<String> getVmArgs() {
|
||||
List<String> vmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
|
||||
List<String> sortedVmArgs = new ArrayList<>(vmArgs);
|
||||
Collections.sort(sortedVmArgs);
|
||||
return sortedVmArgs;
|
||||
}
|
||||
|
||||
private static List<String> getLibJarNames() {
|
||||
List<URL> classLoaderUrls = loadClassLoaderUrls();
|
||||
return extractLibJarNamesFromURLs(classLoaderUrls);
|
||||
}
|
||||
|
||||
private static List<URL> loadClassLoaderUrls() {
|
||||
List<URL> classLoaderUrls = new ArrayList<>();
|
||||
for (ClassLoader classLoader : CURRENT_URL_CLASSLOADER_SET) {
|
||||
try {
|
||||
URLClassLoader webappClassLoader = (URLClassLoader) classLoader;
|
||||
URL[] urls = webappClassLoader.getURLs();
|
||||
classLoaderUrls.addAll(Arrays.asList(urls));
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Load classloader urls exception: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return classLoaderUrls;
|
||||
}
|
||||
|
||||
private static List<String> extractLibJarNamesFromURLs(List<URL> urls) {
|
||||
Set<String> libJarNames = new HashSet<>();
|
||||
for (URL url : urls) {
|
||||
try {
|
||||
String libJarName = extractLibJarName(url);
|
||||
if (libJarName.endsWith(".jar")) {
|
||||
libJarNames.add(libJarName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Extracting library name exception: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
List<String> sortedLibJarNames = new ArrayList<>(libJarNames.size());
|
||||
if (!CollectionUtil.isEmpty(libJarNames)) {
|
||||
sortedLibJarNames.addAll(libJarNames);
|
||||
Collections.sort(sortedLibJarNames);
|
||||
}
|
||||
return sortedLibJarNames;
|
||||
}
|
||||
|
||||
private static String extractLibJarName(URL url) {
|
||||
String protocol = url.getProtocol();
|
||||
if (protocol.equals("file")) {
|
||||
return extractNameFromFile(url.toString());
|
||||
} else if (protocol.equals("jar")) {
|
||||
return extractNameFromJar(url.toString());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractNameFromFile(String fileUri) {
|
||||
int lastIndexOfSeparator = fileUri.lastIndexOf(File.separator);
|
||||
if (lastIndexOfSeparator < 0) {
|
||||
return fileUri;
|
||||
} else {
|
||||
return fileUri.substring(lastIndexOfSeparator + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractNameFromJar(String jarUri) {
|
||||
String uri = jarUri.substring(0, jarUri.lastIndexOf(JAR_SEPARATOR));
|
||||
return extractNameFromFile(uri);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,104 +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 cn.hippo4j.agent.core.os;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class OSUtil {
|
||||
|
||||
private static volatile String OS_NAME;
|
||||
private static volatile String HOST_NAME;
|
||||
private static volatile List<String> IPV4_LIST;
|
||||
private static volatile int PROCESS_NO = 0;
|
||||
|
||||
public static String getOsName() {
|
||||
if (OS_NAME == null) {
|
||||
OS_NAME = System.getProperty("os.name");
|
||||
}
|
||||
return OS_NAME;
|
||||
}
|
||||
|
||||
public static String getHostName() {
|
||||
if (HOST_NAME == null) {
|
||||
try {
|
||||
InetAddress host = InetAddress.getLocalHost();
|
||||
HOST_NAME = host.getHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
HOST_NAME = "unknown";
|
||||
}
|
||||
}
|
||||
return HOST_NAME;
|
||||
}
|
||||
|
||||
public static List<String> getAllIPV4() {
|
||||
if (IPV4_LIST == null) {
|
||||
IPV4_LIST = new LinkedList<>();
|
||||
try {
|
||||
Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
|
||||
while (interfs.hasMoreElements()) {
|
||||
NetworkInterface networkInterface = interfs.nextElement();
|
||||
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
||||
while (inetAddresses.hasMoreElements()) {
|
||||
InetAddress address = inetAddresses.nextElement();
|
||||
if (address instanceof Inet4Address) {
|
||||
String addressStr = address.getHostAddress();
|
||||
if ("127.0.0.1".equals(addressStr)) {
|
||||
continue;
|
||||
} else if ("localhost".equals(addressStr)) {
|
||||
continue;
|
||||
}
|
||||
IPV4_LIST.add(addressStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
|
||||
}
|
||||
}
|
||||
return IPV4_LIST;
|
||||
}
|
||||
|
||||
public static String getIPV4() {
|
||||
final List<String> allIPV4 = getAllIPV4();
|
||||
if (allIPV4.size() > 0) {
|
||||
return allIPV4.get(0);
|
||||
} else {
|
||||
return "no-hostname";
|
||||
}
|
||||
}
|
||||
|
||||
public static int getProcessNo() {
|
||||
if (PROCESS_NO == 0) {
|
||||
try {
|
||||
PROCESS_NO = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
|
||||
} catch (Exception e) {
|
||||
PROCESS_NO = -1;
|
||||
}
|
||||
}
|
||||
return PROCESS_NO;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,27 +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 cn.hippo4j.agent.core.os;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
public class ProcessorUtil {
|
||||
|
||||
public static int getNumberOfProcessors() {
|
||||
return ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
|
||||
}
|
||||
}
|
||||
@ -1,202 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.match.ClassMatch;
|
||||
import cn.hippo4j.agent.core.util.CollectionUtil;
|
||||
import cn.hippo4j.agent.core.util.StringUtil;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic abstract class of all sky-walking auto-instrumentation plugins.
|
||||
* <p>
|
||||
* It provides the outline of enhancing the target class. If you want to know more about enhancing, you should go to see
|
||||
* {@link ClassEnhancePluginDefine}
|
||||
*/
|
||||
public abstract class AbstractClassEnhancePluginDefine {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(AbstractClassEnhancePluginDefine.class);
|
||||
|
||||
/**
|
||||
* New field name.
|
||||
*/
|
||||
public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws";
|
||||
|
||||
/**
|
||||
* Main entrance of enhancing the class.
|
||||
*
|
||||
* @param typeDescription target class description.
|
||||
* @param builder byte-buddy's builder to manipulate target class's bytecode.
|
||||
* @param classLoader load the given transformClass
|
||||
* @return the new builder, or <code>null</code> if not be enhanced.
|
||||
* @throws PluginException when set builder failure.
|
||||
*/
|
||||
public DynamicType.Builder<?> define(TypeDescription typeDescription, DynamicType.Builder<?> builder,
|
||||
ClassLoader classLoader, EnhanceContext context) throws PluginException {
|
||||
String interceptorDefineClassName = this.getClass().getName();
|
||||
String transformClassName = typeDescription.getTypeName();
|
||||
if (StringUtil.isEmpty(transformClassName)) {
|
||||
LOGGER.warn("classname of being intercepted is not defined by {}.", interceptorDefineClassName);
|
||||
return null;
|
||||
}
|
||||
|
||||
LOGGER.debug("prepare to enhance class {} by {}.", transformClassName, interceptorDefineClassName);
|
||||
WitnessFinder finder = WitnessFinder.INSTANCE;
|
||||
/**
|
||||
* find witness classes for enhance class
|
||||
*/
|
||||
String[] witnessClasses = witnessClasses();
|
||||
if (witnessClasses != null) {
|
||||
for (String witnessClass : witnessClasses) {
|
||||
if (!finder.exist(witnessClass, classLoader)) {
|
||||
LOGGER.warn("enhance class {} by plugin {} is not activated. Witness class {} does not exist.", transformClassName, interceptorDefineClassName, witnessClass);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<WitnessMethod> witnessMethods = witnessMethods();
|
||||
if (!CollectionUtil.isEmpty(witnessMethods)) {
|
||||
for (WitnessMethod witnessMethod : witnessMethods) {
|
||||
if (!finder.exist(witnessMethod, classLoader)) {
|
||||
LOGGER.warn("enhance class {} by plugin {} is not activated. Witness method {} does not exist.", transformClassName, interceptorDefineClassName, witnessMethod);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find origin class source code for interceptor
|
||||
*/
|
||||
DynamicType.Builder<?> newClassBuilder = this.enhance(typeDescription, builder, classLoader, context);
|
||||
|
||||
context.initializationStageCompleted();
|
||||
LOGGER.debug("enhance class {} by {} completely.", transformClassName, interceptorDefineClassName);
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin to define how to enhance class. After invoke this method, only means definition is finished.
|
||||
*
|
||||
* @param typeDescription target class description
|
||||
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
|
||||
* @return new byte-buddy's builder for further manipulation.
|
||||
*/
|
||||
protected DynamicType.Builder<?> enhance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader, EnhanceContext context) throws PluginException {
|
||||
newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader);
|
||||
|
||||
newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context);
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhance a class to intercept constructors and class instance methods.
|
||||
*
|
||||
* @param typeDescription target class description
|
||||
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
|
||||
* @return new byte-buddy's builder for further manipulation.
|
||||
*/
|
||||
protected abstract DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException;
|
||||
|
||||
/**
|
||||
* Enhance a class to intercept class static methods.
|
||||
*
|
||||
* @param typeDescription target class description
|
||||
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
|
||||
* @return new byte-buddy's builder for further manipulation.
|
||||
*/
|
||||
protected abstract DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException;
|
||||
|
||||
/**
|
||||
* Define the {@link ClassMatch} for filtering class.
|
||||
*
|
||||
* @return {@link ClassMatch}
|
||||
*/
|
||||
protected abstract ClassMatch enhanceClass();
|
||||
|
||||
/**
|
||||
* Witness classname list. Why need witness classname? Let's see like this: A library existed two released versions
|
||||
* (like 1.0, 2.0), which include the same target classes, but because of version iterator, they may have the same
|
||||
* name, but different methods, or different method arguments list. So, if I want to target the particular version
|
||||
* (let's say 1.0 for example), version number is obvious not an option, this is the moment you need "Witness
|
||||
* classes". You can add any classes only in this particular release version ( something like class
|
||||
* com.company.1.x.A, only in 1.0 ), and you can achieve the goal.
|
||||
*/
|
||||
protected String[] witnessClasses() {
|
||||
return new String[]{};
|
||||
}
|
||||
|
||||
protected List<WitnessMethod> witnessMethods() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBootstrapInstrumentation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor methods intercept point. See {@link ConstructorInterceptPoint}
|
||||
*
|
||||
* @return collections of {@link ConstructorInterceptPoint}
|
||||
*/
|
||||
public abstract ConstructorInterceptPoint[] getConstructorsInterceptPoints();
|
||||
|
||||
/**
|
||||
* Instance methods intercept point. See {@link InstanceMethodsInterceptPoint}
|
||||
*
|
||||
* @return collections of {@link InstanceMethodsInterceptPoint}
|
||||
*/
|
||||
public abstract InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints();
|
||||
|
||||
/**
|
||||
* Instance methods intercept v2 point. See {@link InstanceMethodsInterceptV2Point}
|
||||
*
|
||||
* @return collections of {@link InstanceMethodsInterceptV2Point}
|
||||
*/
|
||||
public abstract InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points();
|
||||
|
||||
/**
|
||||
* Static methods intercept point. See {@link StaticMethodsInterceptPoint}
|
||||
*
|
||||
* @return collections of {@link StaticMethodsInterceptPoint}
|
||||
*/
|
||||
public abstract StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints();
|
||||
|
||||
/**
|
||||
* Instance methods intercept v2 point. See {@link InstanceMethodsInterceptV2Point}
|
||||
*
|
||||
* @return collections of {@link InstanceMethodsInterceptV2Point}
|
||||
*/
|
||||
public abstract StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points();
|
||||
}
|
||||
@ -1,36 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
/**
|
||||
* All ByteBuddy core classes required to expose, including open edge for JDK 9+ module, or Bootstrap instrumentation.
|
||||
*/
|
||||
public class ByteBuddyCoreClasses {
|
||||
|
||||
private static final String SHADE_PACKAGE = "cn.hippo4j.agent.dependencies.";
|
||||
|
||||
public static final String[] CLASSES = {
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.RuntimeType",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.This",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.AllArguments",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.AllArguments$Assignment",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.SuperCall",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.Origin",
|
||||
SHADE_PACKAGE + "net.bytebuddy.implementation.bind.annotation.Morph",
|
||||
};
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.loader.AgentClassLoader;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InstrumentationLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* The plugin can be inserted into the kernel by implementing this spi return PluginDefine list.
|
||||
*/
|
||||
|
||||
public enum DynamicPluginLoader {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public List<AbstractClassEnhancePluginDefine> load(AgentClassLoader classLoader) {
|
||||
List<AbstractClassEnhancePluginDefine> all = new ArrayList<AbstractClassEnhancePluginDefine>();
|
||||
for (InstrumentationLoader instrumentationLoader : ServiceLoader.load(InstrumentationLoader.class, classLoader)) {
|
||||
List<AbstractClassEnhancePluginDefine> plugins = instrumentationLoader.load(classLoader);
|
||||
if (plugins != null && !plugins.isEmpty()) {
|
||||
all.addAll(plugins);
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
}
|
||||
@ -1,51 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine;
|
||||
|
||||
/**
|
||||
* The <code>EnhanceContext</code> represents the context or status for processing a class.
|
||||
* <p>
|
||||
* Based on this context, the plugin core {@link ClassEnhancePluginDefine} knows how to process the specific steps for
|
||||
* every particular plugin.
|
||||
*/
|
||||
public class EnhanceContext {
|
||||
|
||||
private boolean isEnhanced = false;
|
||||
/**
|
||||
* The object has already been enhanced or extended. e.g. added the new field, or implemented the new interface
|
||||
*/
|
||||
private boolean objectExtended = false;
|
||||
|
||||
public boolean isEnhanced() {
|
||||
return isEnhanced;
|
||||
}
|
||||
|
||||
public void initializationStageCompleted() {
|
||||
isEnhanced = true;
|
||||
}
|
||||
|
||||
public boolean isObjectExtended() {
|
||||
return objectExtended;
|
||||
}
|
||||
|
||||
public void extendObjectCompleted() {
|
||||
objectExtended = true;
|
||||
}
|
||||
}
|
||||
@ -1,72 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.boot.AgentPackagePath;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
import cn.hippo4j.common.conf.Config;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The manipulated class output. Write the dynamic classes to the `debugging` folder, when we need to do some debug and
|
||||
* recheck.
|
||||
*/
|
||||
public enum InstrumentDebuggingClass {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstrumentDebuggingClass.class);
|
||||
private File debuggingClassesRootPath;
|
||||
|
||||
public void log(DynamicType dynamicType) {
|
||||
if (!Config.Agent.IS_OPEN_DEBUGGING_CLASS) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* try to do I/O things in synchronized way, to avoid unexpected situations.
|
||||
*/
|
||||
synchronized (INSTANCE) {
|
||||
try {
|
||||
if (debuggingClassesRootPath == null) {
|
||||
try {
|
||||
debuggingClassesRootPath = new File(AgentPackagePath.getPath(), "/debugging");
|
||||
if (!debuggingClassesRootPath.exists()) {
|
||||
debuggingClassesRootPath.mkdir();
|
||||
}
|
||||
} catch (AgentPackageNotFoundException e) {
|
||||
LOGGER.error(e, "Can't find the root path for creating /debugging folder.");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
dynamicType.saveIn(debuggingClassesRootPath);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(e, "Can't save class {} to file." + dynamicType.getTypeDescription().getActualName());
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "Save debugging classes fail.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,81 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.loader.AgentClassLoader;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Plugins finder. Use {@link PluginResourcesResolver} to find all plugins, and ask {@link PluginCfg} to load all plugin
|
||||
* definitions.
|
||||
*/
|
||||
public class PluginBootstrap {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(PluginBootstrap.class);
|
||||
|
||||
/**
|
||||
* load all plugins.
|
||||
*
|
||||
* @return plugin definition list.
|
||||
*/
|
||||
public List<AbstractClassEnhancePluginDefine> loadPlugins() throws AgentPackageNotFoundException {
|
||||
AgentClassLoader.initDefaultLoader();
|
||||
|
||||
PluginResourcesResolver resolver = new PluginResourcesResolver();
|
||||
List<URL> resources = resolver.getResources();
|
||||
|
||||
if (resources == null || resources.size() == 0) {
|
||||
LOGGER.info("no plugin files (hippo4j-plugin.def) found, continue to start application.");
|
||||
return new ArrayList<AbstractClassEnhancePluginDefine>();
|
||||
}
|
||||
|
||||
for (URL pluginUrl : resources) {
|
||||
try {
|
||||
PluginCfg.INSTANCE.load(pluginUrl.openStream());
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "plugin file [{}] init failure.", pluginUrl);
|
||||
}
|
||||
}
|
||||
|
||||
List<PluginDefine> pluginClassList = PluginCfg.INSTANCE.getPluginClassList();
|
||||
|
||||
List<AbstractClassEnhancePluginDefine> plugins = new ArrayList<AbstractClassEnhancePluginDefine>();
|
||||
for (PluginDefine pluginDefine : pluginClassList) {
|
||||
try {
|
||||
LOGGER.debug("loading plugin class {}.", pluginDefine.getDefineClass());
|
||||
AbstractClassEnhancePluginDefine plugin = (AbstractClassEnhancePluginDefine) Class.forName(pluginDefine.getDefineClass(), true, AgentClassLoader
|
||||
.getDefault()).newInstance();
|
||||
plugins.add(plugin);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass());
|
||||
}
|
||||
}
|
||||
|
||||
plugins.addAll(DynamicPluginLoader.INSTANCE.load(AgentClassLoader.getDefault()));
|
||||
|
||||
return plugins;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.exception.IllegalPluginDefineException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum PluginCfg {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(PluginCfg.class);
|
||||
|
||||
private List<PluginDefine> pluginClassList = new ArrayList<PluginDefine>();
|
||||
private PluginSelector pluginSelector = new PluginSelector();
|
||||
|
||||
void load(InputStream input) throws IOException {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
|
||||
String pluginDefine;
|
||||
while ((pluginDefine = reader.readLine()) != null) {
|
||||
try {
|
||||
if (pluginDefine.trim().length() == 0 || pluginDefine.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
PluginDefine plugin = PluginDefine.build(pluginDefine);
|
||||
pluginClassList.add(plugin);
|
||||
} catch (IllegalPluginDefineException e) {
|
||||
LOGGER.error(e, "Failed to format plugin({}) define.", pluginDefine);
|
||||
}
|
||||
}
|
||||
pluginClassList = pluginSelector.select(pluginClassList);
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
public List<PluginDefine> getPluginClassList() {
|
||||
return pluginClassList;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.exception.IllegalPluginDefineException;
|
||||
import cn.hippo4j.agent.core.util.StringUtil;
|
||||
|
||||
public class PluginDefine {
|
||||
|
||||
/**
|
||||
* Plugin name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The class name of plugin defined.
|
||||
*/
|
||||
private String defineClass;
|
||||
|
||||
private PluginDefine(String name, String defineClass) {
|
||||
this.name = name;
|
||||
this.defineClass = defineClass;
|
||||
}
|
||||
|
||||
public static PluginDefine build(String define) throws IllegalPluginDefineException {
|
||||
if (StringUtil.isEmpty(define)) {
|
||||
throw new IllegalPluginDefineException(define);
|
||||
}
|
||||
|
||||
String[] pluginDefine = define.split("=");
|
||||
if (pluginDefine.length != 2) {
|
||||
throw new IllegalPluginDefineException(define);
|
||||
}
|
||||
|
||||
String pluginName = pluginDefine[0];
|
||||
String defineClass = pluginDefine[1];
|
||||
return new PluginDefine(pluginName, defineClass);
|
||||
}
|
||||
|
||||
public String getDefineClass() {
|
||||
return defineClass;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@ -1,31 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
public class PluginException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -6020188711867490724L;
|
||||
|
||||
public PluginException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PluginException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,121 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bytebuddy.AbstractJunction;
|
||||
import cn.hippo4j.agent.core.plugin.match.ClassMatch;
|
||||
import cn.hippo4j.agent.core.plugin.match.IndirectMatch;
|
||||
import cn.hippo4j.agent.core.plugin.match.NameMatch;
|
||||
import cn.hippo4j.agent.core.plugin.match.ProtectiveShieldMatcher;
|
||||
import net.bytebuddy.description.NamedElement;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* The <code>PluginFinder</code> represents a finder , which assist to find the one from the given {@link
|
||||
* AbstractClassEnhancePluginDefine} list.
|
||||
*/
|
||||
public class PluginFinder {
|
||||
|
||||
private final Map<String, LinkedList<AbstractClassEnhancePluginDefine>> nameMatchDefine = new HashMap<String, LinkedList<AbstractClassEnhancePluginDefine>>();
|
||||
private final List<AbstractClassEnhancePluginDefine> signatureMatchDefine = new ArrayList<AbstractClassEnhancePluginDefine>();
|
||||
private final List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefine = new ArrayList<AbstractClassEnhancePluginDefine>();
|
||||
private static boolean IS_PLUGIN_INIT_COMPLETED = false;
|
||||
|
||||
public PluginFinder(List<AbstractClassEnhancePluginDefine> plugins) {
|
||||
for (AbstractClassEnhancePluginDefine plugin : plugins) {
|
||||
ClassMatch match = plugin.enhanceClass();
|
||||
|
||||
if (match == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match instanceof NameMatch) {
|
||||
NameMatch nameMatch = (NameMatch) match;
|
||||
LinkedList<AbstractClassEnhancePluginDefine> pluginDefines = nameMatchDefine.get(nameMatch.getClassName());
|
||||
if (pluginDefines == null) {
|
||||
pluginDefines = new LinkedList<AbstractClassEnhancePluginDefine>();
|
||||
nameMatchDefine.put(nameMatch.getClassName(), pluginDefines);
|
||||
}
|
||||
pluginDefines.add(plugin);
|
||||
} else {
|
||||
signatureMatchDefine.add(plugin);
|
||||
}
|
||||
|
||||
if (plugin.isBootstrapInstrumentation()) {
|
||||
bootstrapClassMatchDefine.add(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<AbstractClassEnhancePluginDefine> find(TypeDescription typeDescription) {
|
||||
List<AbstractClassEnhancePluginDefine> matchedPlugins = new LinkedList<AbstractClassEnhancePluginDefine>();
|
||||
String typeName = typeDescription.getTypeName();
|
||||
if (nameMatchDefine.containsKey(typeName)) {
|
||||
matchedPlugins.addAll(nameMatchDefine.get(typeName));
|
||||
}
|
||||
|
||||
for (AbstractClassEnhancePluginDefine pluginDefine : signatureMatchDefine) {
|
||||
IndirectMatch match = (IndirectMatch) pluginDefine.enhanceClass();
|
||||
if (match.isMatch(typeDescription)) {
|
||||
matchedPlugins.add(pluginDefine);
|
||||
}
|
||||
}
|
||||
|
||||
return matchedPlugins;
|
||||
}
|
||||
|
||||
public ElementMatcher<? super TypeDescription> buildMatch() {
|
||||
ElementMatcher.Junction judge = new AbstractJunction<NamedElement>() {
|
||||
|
||||
@Override
|
||||
public boolean matches(NamedElement target) {
|
||||
return nameMatchDefine.containsKey(target.getActualName());
|
||||
}
|
||||
};
|
||||
judge = judge.and(not(isInterface()));
|
||||
for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) {
|
||||
ClassMatch match = define.enhanceClass();
|
||||
if (match instanceof IndirectMatch) {
|
||||
judge = judge.or(((IndirectMatch) match).buildJunction());
|
||||
}
|
||||
}
|
||||
return new ProtectiveShieldMatcher(judge);
|
||||
}
|
||||
|
||||
public List<AbstractClassEnhancePluginDefine> getBootstrapClassMatchDefine() {
|
||||
return bootstrapClassMatchDefine;
|
||||
}
|
||||
|
||||
public static void pluginInitCompleted() {
|
||||
IS_PLUGIN_INIT_COMPLETED = true;
|
||||
}
|
||||
|
||||
public static boolean isPluginInitCompleted() {
|
||||
return IS_PLUGIN_INIT_COMPLETED;
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.loader.AgentClassLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Use the current classloader to read all plugin define file. The file must be named 'hippo4j-plugin.def'
|
||||
*/
|
||||
public class PluginResourcesResolver {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(PluginResourcesResolver.class);
|
||||
|
||||
public List<URL> getResources() {
|
||||
List<URL> cfgUrlPaths = new ArrayList<URL>();
|
||||
Enumeration<URL> urls;
|
||||
try {
|
||||
urls = AgentClassLoader.getDefault().getResources("hippo4j-plugin.def");
|
||||
|
||||
while (urls.hasMoreElements()) {
|
||||
URL pluginUrl = urls.nextElement();
|
||||
cfgUrlPaths.add(pluginUrl);
|
||||
LOGGER.info("find hippo4j plugin define in {}", pluginUrl);
|
||||
}
|
||||
|
||||
return cfgUrlPaths;
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("read resources failure.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,47 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.hippo4j.common.conf.Config.Plugin.EXCLUDE_PLUGINS;
|
||||
|
||||
/**
|
||||
* Select some plugins in activated plugins
|
||||
*/
|
||||
public class PluginSelector {
|
||||
|
||||
/**
|
||||
* Exclude activated plugins
|
||||
*
|
||||
* @param pluginDefines the pluginDefines is loaded from activations directory or plugins directory
|
||||
* @return real activate plugins
|
||||
* @see Config.Plugin#EXCLUDE_PLUGINS
|
||||
*/
|
||||
public List<PluginDefine> select(List<PluginDefine> pluginDefines) {
|
||||
if (!EXCLUDE_PLUGINS.isEmpty()) {
|
||||
List<String> excludes = Arrays.asList(EXCLUDE_PLUGINS.toLowerCase().split(","));
|
||||
return pluginDefines.stream()
|
||||
.filter(item -> !excludes.contains(item.getName().toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return pluginDefines;
|
||||
}
|
||||
}
|
||||
@ -1,84 +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 cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The <code>WitnessFinder</code> represents a pool of {@link TypePool}s, each {@link TypePool} matches a {@link
|
||||
* ClassLoader}, which helps to find the class declaration existed or not.
|
||||
*/
|
||||
public enum WitnessFinder {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private final Map<ClassLoader, TypePool> poolMap = new HashMap<ClassLoader, TypePool>();
|
||||
|
||||
/**
|
||||
* @param classLoader for finding the witnessClass
|
||||
* @return true, if the given witnessClass exists, through the given classLoader.
|
||||
*/
|
||||
public boolean exist(String witnessClass, ClassLoader classLoader) {
|
||||
return getResolution(witnessClass, classLoader)
|
||||
.isResolved();
|
||||
}
|
||||
|
||||
/**
|
||||
* get TypePool.Resolution of the witness class
|
||||
* @param witnessClass class name
|
||||
* @param classLoader classLoader for finding the witnessClass
|
||||
* @return TypePool.Resolution
|
||||
*/
|
||||
private TypePool.Resolution getResolution(String witnessClass, ClassLoader classLoader) {
|
||||
ClassLoader mappingKey = classLoader == null ? NullClassLoader.INSTANCE : classLoader;
|
||||
if (!poolMap.containsKey(mappingKey)) {
|
||||
synchronized (poolMap) {
|
||||
if (!poolMap.containsKey(mappingKey)) {
|
||||
TypePool classTypePool = classLoader == null ? TypePool.Default.ofBootLoader() : TypePool.Default.of(classLoader);
|
||||
poolMap.put(mappingKey, classTypePool);
|
||||
}
|
||||
}
|
||||
}
|
||||
TypePool typePool = poolMap.get(mappingKey);
|
||||
return typePool.describe(witnessClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classLoader for finding the witness method
|
||||
* @return true, if the given witness method exists, through the given classLoader.
|
||||
*/
|
||||
public boolean exist(WitnessMethod witnessMethod, ClassLoader classLoader) {
|
||||
TypePool.Resolution resolution = getResolution(witnessMethod.getDeclaringClassName(), classLoader);
|
||||
if (!resolution.isResolved()) {
|
||||
return false;
|
||||
}
|
||||
return !resolution.resolve()
|
||||
.getDeclaredMethods()
|
||||
.filter(witnessMethod.getElementMatcher())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class NullClassLoader extends ClassLoader {
|
||||
|
||||
static NullClassLoader INSTANCE = new NullClassLoader();
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* Witness Method for plugin activation
|
||||
*/
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public class WitnessMethod {
|
||||
|
||||
/**
|
||||
* the class or interface name where the witness method is declared.
|
||||
*/
|
||||
@Getter
|
||||
private final String declaringClassName;
|
||||
/**
|
||||
* matcher to match the witness method
|
||||
*/
|
||||
@Getter
|
||||
private final ElementMatcher<? super MethodDescription.InDefinedShape> elementMatcher;
|
||||
|
||||
}
|
||||
@ -1,301 +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 cn.hippo4j.agent.core.plugin.bootstrap;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.AbstractClassEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.ByteBuddyCoreClasses;
|
||||
import cn.hippo4j.agent.core.plugin.InstrumentDebuggingClass;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.PluginFinder;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.jdk9module.JDK9ModuleExporter;
|
||||
import cn.hippo4j.agent.core.plugin.loader.AgentClassLoader;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.dynamic.loading.ClassInjector;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
/**
|
||||
* If there is Bootstrap instrumentation plugin declared in plugin list, BootstrapInstrumentBoost inject the necessary
|
||||
* classes into bootstrap class loader, including generated dynamic delegate classes.
|
||||
*/
|
||||
public class BootstrapInstrumentBoost {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(BootstrapInstrumentBoost.class);
|
||||
|
||||
private static final String[] HIGH_PRIORITY_CLASSES = {
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor",
|
||||
"cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult",
|
||||
|
||||
// interceptor v2
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2",
|
||||
"cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext",
|
||||
};
|
||||
|
||||
private static String INSTANCE_METHOD_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.InstanceMethodInterTemplate";
|
||||
private static String INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.InstanceMethodInterWithOverrideArgsTemplate";
|
||||
private static String CONSTRUCTOR_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.ConstructorInterTemplate";
|
||||
private static String STATIC_METHOD_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.StaticMethodInterTemplate";
|
||||
private static String STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.StaticMethodInterWithOverrideArgsTemplate";
|
||||
|
||||
private static String INSTANCE_METHOD_V2_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.v2.InstanceMethodInterV2Template";
|
||||
private static String INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.v2.InstanceMethodInterV2WithOverrideArgsTemplate";
|
||||
private static String STATIC_METHOD_V2_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.v2.StaticMethodInterV2Template";
|
||||
private static String STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "cn.hippo4j.agent.core.plugin.bootstrap.template.v2.StaticMethodInterV2WithOverrideArgsTemplate";
|
||||
|
||||
public static AgentBuilder inject(PluginFinder pluginFinder, Instrumentation instrumentation,
|
||||
AgentBuilder agentBuilder, JDK9ModuleExporter.EdgeClasses edgeClasses) throws PluginException {
|
||||
Map<String, byte[]> classesTypeMap = new LinkedHashMap<>();
|
||||
|
||||
if (!prepareJREInstrumentation(pluginFinder, classesTypeMap)) {
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
if (!prepareJREInstrumentationV2(pluginFinder, classesTypeMap)) {
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
for (String highPriorityClass : HIGH_PRIORITY_CLASSES) {
|
||||
loadHighPriorityClass(classesTypeMap, highPriorityClass);
|
||||
}
|
||||
for (String highPriorityClass : ByteBuddyCoreClasses.CLASSES) {
|
||||
loadHighPriorityClass(classesTypeMap, highPriorityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare to open edge of necessary classes.
|
||||
*/
|
||||
for (String generatedClass : classesTypeMap.keySet()) {
|
||||
edgeClasses.add(generatedClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the classes into bootstrap class loader by using Unsafe Strategy.
|
||||
* ByteBuddy adapts the sun.misc.Unsafe and jdk.internal.misc.Unsafe automatically.
|
||||
*/
|
||||
ClassInjector.UsingUnsafe.Factory factory = ClassInjector.UsingUnsafe.Factory.resolve(instrumentation);
|
||||
factory.make(null, null).injectRaw(classesTypeMap);
|
||||
agentBuilder = agentBuilder.with(new AgentBuilder.InjectionStrategy.UsingUnsafe.OfFactory(factory));
|
||||
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delegate class name.
|
||||
*
|
||||
* @param methodsInterceptor of original interceptor in the plugin
|
||||
* @return generated delegate class name
|
||||
*/
|
||||
public static String internalDelegate(String methodsInterceptor) {
|
||||
return methodsInterceptor + "_internal";
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the delegate class from current class loader, mostly should be AppClassLoader.
|
||||
*
|
||||
* @param methodsInterceptor of original interceptor in the plugin
|
||||
* @return generated delegate class
|
||||
*/
|
||||
public static Class forInternalDelegateClass(String methodsInterceptor) {
|
||||
try {
|
||||
return Class.forName(internalDelegate(methodsInterceptor));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new PluginException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate dynamic delegate for ByteBuddy
|
||||
*
|
||||
* @param pluginFinder gets the whole plugin list.
|
||||
* @param classesTypeMap hosts the class binary.
|
||||
* @return true if have JRE instrumentation requirement.
|
||||
* @throws PluginException when generate failure.
|
||||
*/
|
||||
private static boolean prepareJREInstrumentation(PluginFinder pluginFinder,
|
||||
Map<String, byte[]> classesTypeMap) throws PluginException {
|
||||
TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader());
|
||||
List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine();
|
||||
for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) {
|
||||
if (Objects.nonNull(define.getInstanceMethodsInterceptPoints())) {
|
||||
for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(define.getConstructorsInterceptPoints())) {
|
||||
for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor());
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(define.getStaticMethodsInterceptPoints())) {
|
||||
for (StaticMethodsInterceptPoint point : define.getStaticMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bootstrapClassMatchDefines.size() > 0;
|
||||
}
|
||||
|
||||
private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder,
|
||||
Map<String, byte[]> classesTypeMap) throws PluginException {
|
||||
TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader());
|
||||
List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine();
|
||||
for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) {
|
||||
if (Objects.nonNull(define.getInstanceMethodsInterceptV2Points())) {
|
||||
for (InstanceMethodsInterceptV2Point point : define.getInstanceMethodsInterceptV2Points()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool,
|
||||
INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_V2_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(define.getStaticMethodsInterceptV2Points())) {
|
||||
for (StaticMethodsInterceptV2Point point : define.getStaticMethodsInterceptV2Points()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool,
|
||||
STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_V2_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bootstrapClassMatchDefines.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the delegator class based on given template class. This is preparation stage level code generation.
|
||||
* <p>
|
||||
* One key step to avoid class confliction between AppClassLoader and BootstrapClassLoader
|
||||
*
|
||||
* @param classesTypeMap hosts injected binary of generated class
|
||||
* @param typePool to generate new class
|
||||
* @param templateClassName represents the class as template in this generation process. The templates are
|
||||
* pre-defined in Hippo4j agent core.
|
||||
*/
|
||||
private static void generateDelegator(Map<String, byte[]> classesTypeMap, TypePool typePool,
|
||||
String templateClassName, String methodsInterceptor) {
|
||||
String internalInterceptorName = internalDelegate(methodsInterceptor);
|
||||
try {
|
||||
TypeDescription templateTypeDescription = typePool.describe(templateClassName).resolve();
|
||||
|
||||
DynamicType.Unloaded interceptorType = new ByteBuddy().redefine(templateTypeDescription, ClassFileLocator.ForClassLoader
|
||||
.of(BootstrapInstrumentBoost.class.getClassLoader()))
|
||||
.name(internalInterceptorName)
|
||||
.field(named("TARGET_INTERCEPTOR"))
|
||||
.value(methodsInterceptor)
|
||||
.make();
|
||||
|
||||
classesTypeMap.put(internalInterceptorName, interceptorType.getBytes());
|
||||
|
||||
InstrumentDebuggingClass.INSTANCE.log(interceptorType);
|
||||
} catch (Exception e) {
|
||||
throw new PluginException("Generate Dynamic plugin failure", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class loaded by this method means it only should be loaded once in Bootstrap classloader, when bootstrap
|
||||
* instrumentation active by any plugin
|
||||
*
|
||||
* @param loadedTypeMap hosts all injected class
|
||||
* @param className to load
|
||||
*/
|
||||
private static void loadHighPriorityClass(Map<String, byte[]> loadedTypeMap,
|
||||
String className) throws PluginException {
|
||||
byte[] enhancedInstanceClassFile;
|
||||
try {
|
||||
String classResourceName = className.replaceAll("\\.", "/") + ".class";
|
||||
InputStream resourceAsStream = AgentClassLoader.getDefault().getResourceAsStream(classResourceName);
|
||||
|
||||
if (resourceAsStream == null) {
|
||||
throw new PluginException("High priority class " + className + " not found.");
|
||||
}
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
|
||||
// read bytes from the input stream and store them in buffer
|
||||
while ((len = resourceAsStream.read(buffer)) != -1) {
|
||||
// write bytes from the buffer into output stream
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
enhancedInstanceClassFile = os.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new PluginException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
loadedTypeMap.put(className, enhancedInstanceClassFile);
|
||||
}
|
||||
}
|
||||
@ -1,102 +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 cn.hippo4j.agent.core.plugin.bootstrap;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
|
||||
/**
|
||||
* The log bridge makes the ILog accessible inside bootstrap classloader, especially for internal interceptor.
|
||||
*/
|
||||
public class BootstrapPluginLogBridge implements IBootstrapLog {
|
||||
|
||||
public static IBootstrapLog getLogger(String clazz) {
|
||||
return new BootstrapPluginLogBridge(clazz);
|
||||
}
|
||||
|
||||
private final ILog logger;
|
||||
|
||||
private BootstrapPluginLogBridge(String clazz) {
|
||||
logger = LogManager.getLogger(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String format) {
|
||||
logger.info(format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String format, Object... arguments) {
|
||||
logger.info(format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String format, Object... arguments) {
|
||||
logger.warn(format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Throwable e, String format, Object... arguments) {
|
||||
logger.warn(e, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String format, Throwable e) {
|
||||
logger.error(format, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Throwable e, String format, Object... arguments) {
|
||||
logger.error(e, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnable() {
|
||||
return logger.isDebugEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnable() {
|
||||
return logger.isInfoEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnable() {
|
||||
return logger.isWarnEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnable() {
|
||||
return logger.isErrorEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String format) {
|
||||
logger.debug(format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String format, Object... arguments) {
|
||||
logger.debug(format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String format) {
|
||||
logger.error(format);
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.bootstrap;
|
||||
|
||||
/**
|
||||
* The log interface used in bootstrap internal interceptors.
|
||||
* <p>
|
||||
* Never used in any plugin or tracing core.
|
||||
*/
|
||||
public interface IBootstrapLog {
|
||||
|
||||
void info(String format);
|
||||
|
||||
void info(String format, Object... arguments);
|
||||
|
||||
void warn(String format, Object... arguments);
|
||||
|
||||
void warn(Throwable e, String format, Object... arguments);
|
||||
|
||||
void error(String format, Throwable e);
|
||||
|
||||
void error(Throwable e, String format, Object... arguments);
|
||||
|
||||
boolean isDebugEnable();
|
||||
|
||||
boolean isInfoEnable();
|
||||
|
||||
boolean isWarnEnable();
|
||||
|
||||
boolean isErrorEnable();
|
||||
|
||||
void debug(String format);
|
||||
|
||||
void debug(String format, Object... arguments);
|
||||
|
||||
void error(String format);
|
||||
}
|
||||
@ -1,79 +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 cn.hippo4j.agent.core.plugin.bootstrap.template;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
public class ConstructorInterTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceConstructorInterceptor INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target constructor.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all constructor arguments
|
||||
*/
|
||||
@RuntimeType
|
||||
public static void intercept(@This Object obj, @AllArguments Object[] allArguments) {
|
||||
try {
|
||||
prepare();
|
||||
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
if (INTERCEPTOR == null) {
|
||||
return;
|
||||
}
|
||||
INTERCEPTOR.onConstruct(targetObject, allArguments);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("ConstructorInter failure.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,125 +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 cn.hippo4j.agent.core.plugin.bootstrap.template;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class InstanceMethodInterTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptor INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,125 +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 cn.hippo4j.agent.core.plugin.bootstrap.template;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class InstanceMethodInterWithOverrideArgsTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptor INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Morph OverrideCallable zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,114 +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 cn.hippo4j.agent.core.plugin.bootstrap.template;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class StaticMethodInterTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptor INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@SuperCall Callable<?> zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,114 +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 cn.hippo4j.agent.core.plugin.bootstrap.template;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class StaticMethodInterWithOverrideArgsTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptor INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,128 +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 cn.hippo4j.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class InstanceMethodInterV2Template {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,128 +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 cn.hippo4j.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class InstanceMethodInterV2WithOverrideArgsTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Morph OverrideCallable zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,117 +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 cn.hippo4j.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class StaticMethodInterV2Template {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@SuperCall Callable<?> zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,117 +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 cn.hippo4j.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class StaticMethodInterV2WithOverrideArgsTemplate {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,33 +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 cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public abstract class AbstractJunction<V> implements ElementMatcher.Junction<V> {
|
||||
|
||||
@Override
|
||||
public <U extends V> Junction<U> and(ElementMatcher<? super U> other) {
|
||||
return new Conjunction<U>(this, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends V> Junction<U> or(ElementMatcher<? super U> other) {
|
||||
return new Disjunction<U>(this, other);
|
||||
}
|
||||
}
|
||||
@ -1,70 +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 cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
||||
import net.bytebuddy.description.annotation.AnnotationSource;
|
||||
import net.bytebuddy.matcher.CollectionItemMatcher;
|
||||
import net.bytebuddy.matcher.DeclaringAnnotationMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* Annotation Type match. Similar with {@link net.bytebuddy.matcher.ElementMatchers#isAnnotatedWith}, the only different
|
||||
* between them is this match use {@link String} to declare the type, instead of {@link Class}. This can avoid the
|
||||
* classloader risk.
|
||||
* <p>
|
||||
* 2019-08-15
|
||||
*/
|
||||
public class AnnotationTypeNameMatch<T extends AnnotationDescription> implements ElementMatcher<T> {
|
||||
|
||||
/**
|
||||
* the target annotation type
|
||||
*/
|
||||
private String annotationTypeName;
|
||||
|
||||
/**
|
||||
* declare the match target method with the certain type.
|
||||
*
|
||||
* @param annotationTypeName target annotation type
|
||||
*/
|
||||
private AnnotationTypeNameMatch(String annotationTypeName) {
|
||||
this.annotationTypeName = annotationTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(T target) {
|
||||
return target.getAnnotationType().asErasure().getName().equals(annotationTypeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method to create {@link AnnotationTypeNameMatch} This is a delegate method to follow byte-buddy {@link
|
||||
* ElementMatcher}'s code style.
|
||||
*
|
||||
* @param annotationTypeName target annotation type
|
||||
* @param <T> The type of the object that is being matched.
|
||||
* @return new {@link AnnotationTypeNameMatch} instance.
|
||||
*/
|
||||
public static <T extends AnnotationSource> Junction<T> isAnnotatedWithType(
|
||||
String annotationTypeName) {
|
||||
final AnnotationTypeNameMatch<AnnotationDescription> matcher = new AnnotationTypeNameMatch<AnnotationDescription>(annotationTypeName);
|
||||
return new DeclaringAnnotationMatcher<T>(new CollectionItemMatcher<AnnotationDescription>(matcher));
|
||||
}
|
||||
}
|
||||
@ -1,82 +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 cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.method.ParameterList;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* Argument Type match. Similar with {@link net.bytebuddy.matcher.ElementMatchers#takesArgument}, the only different
|
||||
* between them is this match use {@link String} to declare the type, instead of {@link Class}. This can avoid the
|
||||
* classloader risk.
|
||||
* <p>
|
||||
*/
|
||||
public class ArgumentTypeNameMatch implements ElementMatcher<MethodDescription> {
|
||||
|
||||
/**
|
||||
* the index of arguments list.
|
||||
*/
|
||||
private int index;
|
||||
|
||||
/**
|
||||
* the target argument type at {@link ArgumentTypeNameMatch#index} of the arguments list.
|
||||
*/
|
||||
private String argumentTypeName;
|
||||
|
||||
/**
|
||||
* declare the match target method with the certain index and type.
|
||||
*
|
||||
* @param index the index of arguments list.
|
||||
* @param argumentTypeName target argument type
|
||||
*/
|
||||
private ArgumentTypeNameMatch(int index, String argumentTypeName) {
|
||||
ArrayTypeNameChecker.check(argumentTypeName);
|
||||
|
||||
this.index = index;
|
||||
this.argumentTypeName = argumentTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the target method.
|
||||
*
|
||||
* @param target target method description.
|
||||
* @return true if matched. or false.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(MethodDescription target) {
|
||||
ParameterList<?> parameters = target.getParameters();
|
||||
if (parameters.size() > index) {
|
||||
return parameters.get(index).getType().asErasure().getName().equals(argumentTypeName);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method to create {@link ArgumentTypeNameMatch} This is a delegate method to follow byte-buddy {@link
|
||||
* ElementMatcher}'s code style.
|
||||
*
|
||||
* @param index the index of arguments list.
|
||||
* @param argumentTypeName target argument type
|
||||
* @return new {@link ArgumentTypeNameMatch} instance.
|
||||
*/
|
||||
public static ElementMatcher<MethodDescription> takesArgumentWithType(int index, String argumentTypeName) {
|
||||
return new ArgumentTypeNameMatch(index, argumentTypeName);
|
||||
}
|
||||
}
|
||||
@ -1,27 +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 cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
public class ArrayTypeNameChecker {
|
||||
|
||||
public static void check(String typeName) {
|
||||
if (typeName.endsWith("[]")) {
|
||||
throw new IllegalArgumentException("Please use [Lxxx; to define an Array type, and ref to JVM Specification for details");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,196 +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 cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
import cn.hippo4j.agent.core.boot.AgentPackagePath;
|
||||
import cn.hippo4j.agent.core.util.FileUtils;
|
||||
import cn.hippo4j.agent.core.util.IOUtils;
|
||||
import cn.hippo4j.common.boot.AgentPackageNotFoundException;
|
||||
import cn.hippo4j.common.boot.ClassCacheMode;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
|
||||
import net.bytebuddy.utility.RandomString;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Wrapper classFileTransformer of ByteBuddy, save the enhanced bytecode to memory cache or file cache,
|
||||
* and automatically load the previously generated bytecode during the second retransform,
|
||||
* to solve the problem that ByteBuddy generates auxiliary classes with different random names every time.
|
||||
* Allow other javaagent to enhance those classes that enhanced by Hippo4j agent.
|
||||
*/
|
||||
public class CacheableTransformerDecorator implements AgentBuilder.TransformerDecorator {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(CacheableTransformerDecorator.class);
|
||||
|
||||
private final ClassCacheMode cacheMode;
|
||||
private ClassCacheResolver cacheResolver;
|
||||
|
||||
public CacheableTransformerDecorator(ClassCacheMode cacheMode) throws IOException {
|
||||
this.cacheMode = cacheMode;
|
||||
initClassCache();
|
||||
}
|
||||
|
||||
private void initClassCache() throws IOException {
|
||||
if (this.cacheMode.equals(ClassCacheMode.FILE)) {
|
||||
String cacheDirBase = null;
|
||||
try {
|
||||
cacheDirBase = AgentPackagePath.getPath() + "/class-cache";
|
||||
} catch (AgentPackageNotFoundException e) {
|
||||
throw new IOException("Can't find the root path for creating /class-cache folder.");
|
||||
}
|
||||
File cacheDir = new File(cacheDirBase + "/class-cache-" + RandomString.make());
|
||||
if (!cacheDir.exists()) {
|
||||
cacheDir.mkdirs();
|
||||
}
|
||||
if (!cacheDir.exists()) {
|
||||
throw new IOException("Create class cache dir failure");
|
||||
}
|
||||
|
||||
cacheResolver = new FileCacheResolver(cacheDir);
|
||||
} else {
|
||||
cacheResolver = new MemoryCacheResolver();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResettableClassFileTransformer decorate(ResettableClassFileTransformer classFileTransformer) {
|
||||
return new ResettableClassFileTransformer.WithDelegation(classFileTransformer) {
|
||||
|
||||
@Override
|
||||
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
|
||||
// load from cache
|
||||
byte[] classCache = cacheResolver.getClassCache(loader, className);
|
||||
if (classCache != null) {
|
||||
return classCache;
|
||||
}
|
||||
|
||||
// transform class
|
||||
classfileBuffer = classFileTransformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
|
||||
|
||||
// save to cache
|
||||
if (classfileBuffer != null) {
|
||||
cacheResolver.putClassCache(loader, className, classfileBuffer);
|
||||
}
|
||||
|
||||
return classfileBuffer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String getClassLoaderHash(ClassLoader loader) {
|
||||
String classloader;
|
||||
if (loader != null) {
|
||||
classloader = Integer.toHexString(loader.hashCode());
|
||||
} else {
|
||||
// classloader is null for BootstrapClassLoader
|
||||
classloader = "00000000";
|
||||
}
|
||||
return classloader;
|
||||
}
|
||||
|
||||
interface ClassCacheResolver {
|
||||
|
||||
byte[] getClassCache(ClassLoader loader, String className);
|
||||
|
||||
void putClassCache(ClassLoader loader, String className, byte[] classfileBuffer);
|
||||
}
|
||||
|
||||
static class MemoryCacheResolver implements ClassCacheResolver {
|
||||
|
||||
// classloaderHashcode@className -> class bytes
|
||||
private Map<String, byte[]> classCacheMap = new ConcurrentHashMap<String, byte[]>();
|
||||
|
||||
@Override
|
||||
public byte[] getClassCache(ClassLoader loader, String className) {
|
||||
String cacheKey = getCacheKey(loader, className);
|
||||
return classCacheMap.get(cacheKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putClassCache(ClassLoader loader, String className, byte[] classfileBuffer) {
|
||||
String cacheKey = getCacheKey(loader, className);
|
||||
classCacheMap.put(cacheKey, classfileBuffer);
|
||||
}
|
||||
|
||||
private String getCacheKey(ClassLoader loader, String className) {
|
||||
return getClassLoaderHash(loader) + "@" + className;
|
||||
}
|
||||
}
|
||||
|
||||
static class FileCacheResolver implements ClassCacheResolver {
|
||||
|
||||
private final File cacheDir;
|
||||
|
||||
FileCacheResolver(File cacheDir) {
|
||||
this.cacheDir = cacheDir;
|
||||
|
||||
// clean cache dir on exit
|
||||
FileUtils.deleteDirectoryOnExit(cacheDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getClassCache(ClassLoader loader, String className) {
|
||||
// load from cache
|
||||
File cacheFile = getCacheFile(loader, className);
|
||||
if (cacheFile.exists()) {
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(cacheFile);
|
||||
return IOUtils.toByteArray(fileInputStream);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("load class bytes from cache file failure", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileInputStream);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putClassCache(ClassLoader loader, String className, byte[] classfileBuffer) {
|
||||
File cacheFile = getCacheFile(loader, className);
|
||||
cacheFile.getParentFile().mkdirs();
|
||||
FileOutputStream output = null;
|
||||
try {
|
||||
output = new FileOutputStream(cacheFile);
|
||||
IOUtils.copy(new ByteArrayInputStream(classfileBuffer), output);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("save class bytes to cache file failure", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(output);
|
||||
}
|
||||
}
|
||||
|
||||
private File getCacheFile(ClassLoader loader, String className) {
|
||||
String filename = getClassLoaderHash(loader) + "/" + className.replace('.', '/') + ".class";
|
||||
return new File(cacheDir, filename);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.bytebuddy;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* Return Type match. Similar with {@link net.bytebuddy.matcher.ElementMatchers#returns}, the only different between
|
||||
* them is this match use {@link String} to declare the type, instead of {@link Class}. This can avoid the classloader
|
||||
* risk.
|
||||
* <p>
|
||||
* 2019-08-15
|
||||
*/
|
||||
public class ReturnTypeNameMatch implements ElementMatcher<MethodDescription> {
|
||||
|
||||
/**
|
||||
* the target return type
|
||||
*/
|
||||
private String returnTypeName;
|
||||
|
||||
/**
|
||||
* declare the match target method with the certain type.
|
||||
*
|
||||
* @param returnTypeName target return type
|
||||
*/
|
||||
private ReturnTypeNameMatch(String returnTypeName) {
|
||||
ArrayTypeNameChecker.check(returnTypeName);
|
||||
this.returnTypeName = returnTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(MethodDescription target) {
|
||||
return target.getReturnType().asErasure().getName().equals(returnTypeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method to create {@link ReturnTypeNameMatch} This is a delegate method to follow byte-buddy {@link
|
||||
* ElementMatcher}'s code style.
|
||||
*
|
||||
* @param returnTypeName target return type
|
||||
* @return new {@link ReturnTypeNameMatch} instance.
|
||||
*/
|
||||
public static ElementMatcher<MethodDescription> returnsWithType(String returnTypeName) {
|
||||
return new ReturnTypeNameMatch(returnTypeName);
|
||||
}
|
||||
}
|
||||
@ -1,28 +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 cn.hippo4j.agent.core.plugin.exception;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that a illegal format plugin definition has been defined in hippo4j-plugin.define.
|
||||
*/
|
||||
public class IllegalPluginDefineException extends Exception {
|
||||
|
||||
public IllegalPluginDefineException(String define) {
|
||||
super("Illegal plugin define : " + define);
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* One of the three "Intercept Point". "Intercept Point" is a definition about where and how intercept happens. In this
|
||||
* "Intercept Point", the definition targets class's constructors, and the interceptor.
|
||||
* <p>
|
||||
* ref to two others: {@link StaticMethodsInterceptPoint} and {@link InstanceMethodsInterceptPoint}
|
||||
* <p>
|
||||
*/
|
||||
public interface ConstructorInterceptPoint {
|
||||
|
||||
/**
|
||||
* Constructor matcher
|
||||
*
|
||||
* @return matcher instance.
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getConstructorMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must be a instance of {@link
|
||||
* cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor}
|
||||
*/
|
||||
String getConstructorInterceptor();
|
||||
}
|
||||
@ -1,25 +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 cn.hippo4j.agent.core.plugin.interceptor;
|
||||
|
||||
/**
|
||||
* this interface for those who only want to enhance declared method in case of some unexpected issue, such as spring
|
||||
* controller
|
||||
*/
|
||||
public interface DeclaredInstanceMethodsInterceptPoint extends InstanceMethodsInterceptPoint {
|
||||
}
|
||||
@ -1,33 +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 cn.hippo4j.agent.core.plugin.interceptor;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
|
||||
public class EnhanceException extends PluginException {
|
||||
|
||||
private static final long serialVersionUID = -2234782755784217255L;
|
||||
|
||||
public EnhanceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EnhanceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* One of the three "Intercept Point". "Intercept Point" is a definition about where and how intercept happens. In this
|
||||
* "Intercept Point", the definition targets class's instance methods, and the interceptor.
|
||||
* <p>
|
||||
* ref to two others: {@link ConstructorInterceptPoint} and {@link StaticMethodsInterceptPoint}
|
||||
* <p>
|
||||
*/
|
||||
public interface InstanceMethodsInterceptPoint {
|
||||
|
||||
/**
|
||||
* class instance methods matcher.
|
||||
*
|
||||
* @return methods matcher
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getMethodsMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must instanceof InstanceMethodsAroundInterceptor.
|
||||
*/
|
||||
String getMethodsInterceptor();
|
||||
|
||||
boolean isOverrideArgs();
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* One of the three "Intercept Point". "Intercept Point" is a definition about where and how intercept happens. In this
|
||||
* "Intercept Point", the definition targets class's static methods, and the interceptor.
|
||||
* <p>
|
||||
* ref to two others: {@link ConstructorInterceptPoint} and {@link InstanceMethodsInterceptPoint}
|
||||
* <p>
|
||||
*/
|
||||
public interface StaticMethodsInterceptPoint {
|
||||
|
||||
/**
|
||||
* static methods matcher.
|
||||
*
|
||||
* @return matcher instance.
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getMethodsMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must instanceof StaticMethodsAroundInterceptor.
|
||||
*/
|
||||
String getMethodsInterceptor();
|
||||
|
||||
boolean isOverrideArgs();
|
||||
}
|
||||
@ -1,75 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This assist help all bootstrap class core interceptor.
|
||||
*/
|
||||
public class BootstrapInterRuntimeAssist {
|
||||
|
||||
private static final String AGENT_CLASSLOADER_DEFAULT = "cn.hippo4j.agent.core.plugin.loader.AgentClassLoader";
|
||||
private static final String DEFAULT_AGENT_CLASSLOADER_INSTANCE = "DEFAULT_LOADER";
|
||||
private static final String LOG_MANAGER_CLASS = "cn.hippo4j.agent.core.plugin.bootstrap.BootstrapPluginLogBridge";
|
||||
private static final String LOG_MANAGER_GET_LOGGER_METHOD = "getLogger";
|
||||
private static final PrintStream OUT = System.out;
|
||||
|
||||
public static ClassLoader getAgentClassLoader() {
|
||||
try {
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
if (loader == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> agentClassLoaderClass = Class.forName(AGENT_CLASSLOADER_DEFAULT, true, loader);
|
||||
Field defaultLoaderField = agentClassLoaderClass.getDeclaredField(DEFAULT_AGENT_CLASSLOADER_INSTANCE);
|
||||
defaultLoaderField.setAccessible(true);
|
||||
ClassLoader defaultAgentClassLoader = (ClassLoader) defaultLoaderField.get(null);
|
||||
|
||||
return defaultAgentClassLoader;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(OUT);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static IBootstrapLog getLogger(ClassLoader defaultAgentClassLoader, String interceptor) {
|
||||
try {
|
||||
Class<?> logManagerClass = Class.forName(LOG_MANAGER_CLASS, true, defaultAgentClassLoader);
|
||||
Method getLogger = logManagerClass.getMethod(LOG_MANAGER_GET_LOGGER_METHOD, String.class);
|
||||
return (IBootstrapLog) getLogger.invoke(null, interceptor + "_internal");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(OUT);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T createInterceptor(ClassLoader defaultAgentClassLoader, String className, IBootstrapLog log) {
|
||||
try {
|
||||
Class<?> interceptor = Class.forName(className, true, defaultAgentClassLoader);
|
||||
return (T) interceptor.newInstance();
|
||||
} catch (Exception e) {
|
||||
log.error(e, "Interceptor[{}] not found", className);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,238 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.AbstractClassEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.EnhanceContext;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.BootstrapInstrumentBoost;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.DeclaredInstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.EnhanceException;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.util.StringUtil;
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_VOLATILE;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* This class controls all enhance operations, including enhance constructors, instance methods and static methods. All
|
||||
* the enhances base on three types interceptor point: {@link ConstructorInterceptPoint}, {@link
|
||||
* InstanceMethodsInterceptPoint} and {@link StaticMethodsInterceptPoint} If plugin is going to enhance constructors,
|
||||
* instance methods, or both, {@link ClassEnhancePluginDefine} will add a field of {@link Object} type.
|
||||
*/
|
||||
public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(ClassEnhancePluginDefine.class);
|
||||
|
||||
/**
|
||||
* Enhance a class to intercept constructors and class instance methods.
|
||||
*
|
||||
* @param typeDescription target class description
|
||||
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
|
||||
* @return new byte-buddy's builder for further manipulation.
|
||||
*/
|
||||
@Override
|
||||
protected DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException {
|
||||
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
|
||||
InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = getInstanceMethodsInterceptPoints();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
boolean existedConstructorInterceptPoint = false;
|
||||
if (constructorInterceptPoints != null && constructorInterceptPoints.length > 0) {
|
||||
existedConstructorInterceptPoint = true;
|
||||
}
|
||||
boolean existedMethodsInterceptPoints = false;
|
||||
if (instanceMethodsInterceptPoints != null && instanceMethodsInterceptPoints.length > 0) {
|
||||
existedMethodsInterceptPoints = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* nothing need to be enhanced in class instance, maybe need enhance static methods.
|
||||
*/
|
||||
if (!existedConstructorInterceptPoint && !existedMethodsInterceptPoints) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulate class source code.<br/>
|
||||
*
|
||||
* new class need:<br/>
|
||||
* 1.Add field, name {@link #CONTEXT_ATTR_NAME}.
|
||||
* 2.Add a field accessor for this field.
|
||||
*
|
||||
* And make sure the source codes manipulation only occurs once.
|
||||
*
|
||||
*/
|
||||
if (!typeDescription.isAssignableTo(EnhancedInstance.class)) {
|
||||
if (!context.isObjectExtended()) {
|
||||
newClassBuilder = newClassBuilder.defineField(
|
||||
CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE)
|
||||
.implement(EnhancedInstance.class)
|
||||
.intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME));
|
||||
context.extendObjectCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. enhance constructors
|
||||
*/
|
||||
if (existedConstructorInterceptPoint) {
|
||||
for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher())
|
||||
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost
|
||||
.forInternalDelegateClass(constructorInterceptPoint
|
||||
.getConstructorInterceptor()))));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher())
|
||||
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new ConstructorInter(constructorInterceptPoint
|
||||
.getConstructorInterceptor(), classLoader))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. enhance instance methods
|
||||
*/
|
||||
if (existedMethodsInterceptPoints) {
|
||||
for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) {
|
||||
String interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException("no InstanceMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
|
||||
if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) {
|
||||
junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
|
||||
}
|
||||
if (instanceMethodsInterceptPoint.isOverrideArgs()) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader)));
|
||||
}
|
||||
} else {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new InstMethodsInter(interceptor, classLoader)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhance a class to intercept class static methods.
|
||||
*
|
||||
* @param typeDescription target class description
|
||||
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
|
||||
* @return new byte-buddy's builder for further manipulation.
|
||||
*/
|
||||
@Override
|
||||
protected DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException {
|
||||
StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
if (staticMethodsInterceptPoints == null || staticMethodsInterceptPoints.length == 0) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
for (StaticMethodsInterceptPoint staticMethodsInterceptPoint : staticMethodsInterceptPoints) {
|
||||
String interceptor = staticMethodsInterceptPoint.getMethodsInterceptor();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException("no StaticMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
|
||||
if (staticMethodsInterceptPoint.isOverrideArgs()) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(new StaticMethodsInterWithOverrideArgs(interceptor)));
|
||||
}
|
||||
} else {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new StaticMethodsInter(interceptor)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 instance methods.
|
||||
*/
|
||||
@Override
|
||||
public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 static methods.
|
||||
*/
|
||||
@Override
|
||||
public StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class instance methods. Actually, inherit from {@link
|
||||
* ClassInstanceMethodsEnhancePluginDefine} has no differences with inherit from {@link ClassEnhancePluginDefine}. Just
|
||||
* override {@link ClassEnhancePluginDefine#getStaticMethodsInterceptPoints}, and return NULL, which means nothing to
|
||||
* enhance.
|
||||
*/
|
||||
public abstract class ClassInstanceMethodsEnhancePluginDefine extends ClassEnhancePluginDefine {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no static methods.
|
||||
*/
|
||||
@Override
|
||||
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class static methods. Actually, inherit from {@link
|
||||
* ClassStaticMethodsEnhancePluginDefine} has no differences with inherit from {@link ClassEnhancePluginDefine}. Just
|
||||
* override {@link ClassEnhancePluginDefine#getConstructorsInterceptPoints} and {@link
|
||||
* ClassEnhancePluginDefine#getInstanceMethodsInterceptPoints}, and return NULL, which means nothing to enhance.
|
||||
*/
|
||||
public abstract class ClassStaticMethodsEnhancePluginDefine extends ClassEnhancePluginDefine {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no constructors.
|
||||
*/
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no instance methods.
|
||||
*/
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept constructor methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class ConstructorInter {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(ConstructorInter.class);
|
||||
|
||||
/**
|
||||
* An {@link InstanceConstructorInterceptor} This name should only stay in {@link String}, the real {@link Class}
|
||||
* type will trigger classloader failure. If you want to know more, please check on books about Classloader or
|
||||
* Classloader appointment mechanism.
|
||||
*/
|
||||
private InstanceConstructorInterceptor interceptor;
|
||||
|
||||
/**
|
||||
* @param constructorInterceptorClassName class full name.
|
||||
*/
|
||||
public ConstructorInter(String constructorInterceptorClassName, ClassLoader classLoader) throws PluginException {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceConstructorInterceptorV2.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target constructor.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all constructor arguments
|
||||
*/
|
||||
@RuntimeType
|
||||
public void intercept(@This Object obj, @AllArguments Object[] allArguments) {
|
||||
try {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
interceptor.onConstruct(targetObject, allArguments);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("ConstructorInter failure.", t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,25 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
public interface EnhancedInstance {
|
||||
|
||||
Object getHippo4jDynamicField();
|
||||
|
||||
void setHippo4jDynamicField(Object value);
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInter {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInter.class);
|
||||
|
||||
/**
|
||||
* An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class}
|
||||
* type will trigger classloader failure. If you want to know more, please check on books about Classloader or
|
||||
* Classloader appointment mechanism.
|
||||
*/
|
||||
private InstanceMethodsAroundInterceptor interceptor;
|
||||
|
||||
/**
|
||||
* @param instanceMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public InstMethodsInter(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,104 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInterWithOverrideArgs {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterWithOverrideArgs.class);
|
||||
|
||||
/**
|
||||
* An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class}
|
||||
* type will trigger classloader failure. If you want to know more, please check on books about Classloader or
|
||||
* Classloader appointment mechanism.
|
||||
*/
|
||||
private InstanceMethodsAroundInterceptor interceptor;
|
||||
|
||||
/**
|
||||
* @param instanceMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public InstMethodsInterWithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,31 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
/**
|
||||
* The instance constructor's interceptor interface. Any plugin, which wants to intercept constructor, must implement
|
||||
* this interface.
|
||||
* <p>
|
||||
*/
|
||||
public interface InstanceConstructorInterceptor {
|
||||
|
||||
/**
|
||||
* Called after the origin constructor invocation.
|
||||
*/
|
||||
void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable;
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A interceptor, which intercept method's invocation. The target methods will be defined in {@link
|
||||
* ClassEnhancePluginDefine}'s subclass, most likely in {@link ClassInstanceMethodsEnhancePluginDefine}
|
||||
*/
|
||||
public interface InstanceMethodsAroundInterceptor {
|
||||
|
||||
/**
|
||||
* called before target method invocation.
|
||||
*
|
||||
* @param result change this result, if you want to truncate the method.
|
||||
*/
|
||||
void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable;
|
||||
|
||||
/**
|
||||
* called after target method invocation. Even method's invocation triggers an exception.
|
||||
*
|
||||
* @param ret the method's original return value. May be null if the method triggers an exception.
|
||||
* @return the method's actual return value.
|
||||
*/
|
||||
Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable;
|
||||
|
||||
/**
|
||||
* called when occur exception.
|
||||
*
|
||||
* @param t the exception occur.
|
||||
*/
|
||||
void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t);
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This is a method return value manipulator. When a interceptor's method, such as {@link
|
||||
* InstanceMethodsAroundInterceptor#beforeMethod(EnhancedInstance, Method, Object[], Class[], MethodInterceptResult)}
|
||||
* (org.apache.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext, has this as a method argument,
|
||||
* the interceptor can manipulate the method's return value. <p> The new value set to this object, by {@link
|
||||
* MethodInterceptResult#defineReturnValue(Object)}, will override the origin return value.
|
||||
*/
|
||||
public class MethodInterceptResult {
|
||||
|
||||
private boolean isContinue = true;
|
||||
|
||||
private Object ret = null;
|
||||
|
||||
/**
|
||||
* define the new return value.
|
||||
*
|
||||
* @param ret new return value.
|
||||
*/
|
||||
public void defineReturnValue(Object ret) {
|
||||
this.isContinue = false;
|
||||
this.ret = ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, will trigger method interceptor({@link InstMethodsInter} and {@link StaticMethodsInter}) to invoke
|
||||
* the origin method. Otherwise, not.
|
||||
*/
|
||||
public boolean isContinue() {
|
||||
return isContinue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the new return value.
|
||||
*/
|
||||
public Object _ret() {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,23 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
public interface OverrideCallable {
|
||||
|
||||
Object call(Object[] args);
|
||||
}
|
||||
@ -1,51 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The static method's interceptor interface. Any plugin, which wants to intercept static methods, must implement this
|
||||
* interface.
|
||||
*/
|
||||
public interface StaticMethodsAroundInterceptor {
|
||||
|
||||
/**
|
||||
* called before target method invocation.
|
||||
*
|
||||
* @param result change this result, if you want to truncate the method.
|
||||
*/
|
||||
void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
MethodInterceptResult result);
|
||||
|
||||
/**
|
||||
* called after target method invocation. Even method's invocation triggers an exception.
|
||||
*
|
||||
* @param ret the method's original return value.
|
||||
* @return the method's actual return value.
|
||||
*/
|
||||
Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Object ret);
|
||||
|
||||
/**
|
||||
* called when occur exception.
|
||||
*
|
||||
* @param t the exception occur.
|
||||
*/
|
||||
void handleMethodException(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
Throwable t);
|
||||
}
|
||||
@ -1,102 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class static methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class StaticMethodsInter {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInter.class);
|
||||
|
||||
/**
|
||||
* A class full name, and instanceof {@link StaticMethodsAroundInterceptor} This name should only stay in {@link
|
||||
* String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on
|
||||
* books about Classloader or Classloader appointment mechanism.
|
||||
*/
|
||||
private String staticMethodsAroundInterceptorClassName;
|
||||
|
||||
/**
|
||||
* Set the name of {@link StaticMethodsInter#staticMethodsAroundInterceptorClassName}
|
||||
*
|
||||
* @param staticMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public StaticMethodsInter(String staticMethodsAroundInterceptorClassName) {
|
||||
this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@SuperCall Callable<?> zuper) throws Throwable {
|
||||
StaticMethodsAroundInterceptor interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz
|
||||
.getClassLoader());
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,101 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class static methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class StaticMethodsInterWithOverrideArgs {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterWithOverrideArgs.class);
|
||||
|
||||
/**
|
||||
* A class full name, and instanceof {@link StaticMethodsAroundInterceptor} This name should only stay in {@link
|
||||
* String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on
|
||||
* books about Classloader or Classloader appointment mechanism.
|
||||
*/
|
||||
private String staticMethodsAroundInterceptorClassName;
|
||||
|
||||
/**
|
||||
* Set the name of {@link StaticMethodsInterWithOverrideArgs#staticMethodsAroundInterceptorClassName}
|
||||
*
|
||||
* @param staticMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public StaticMethodsInterWithOverrideArgs(String staticMethodsAroundInterceptorClassName) {
|
||||
this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
StaticMethodsAroundInterceptor interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz
|
||||
.getClassLoader());
|
||||
|
||||
MethodInterceptResult result = new MethodInterceptResult();
|
||||
try {
|
||||
interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!result.isContinue()) {
|
||||
ret = result._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,207 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.AbstractClassEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.EnhanceContext;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.bootstrap.BootstrapInstrumentBoost;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.EnhanceException;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ConstructorInter;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.ConstructorInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.DeclaredInstanceMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import cn.hippo4j.agent.core.util.StringUtil;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_VOLATILE;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* This class controls all enhance operations, including enhance constructors, instance methods and static methods. All
|
||||
* the enhances base on three types interceptor point: {@link ConstructorInterceptV2Point}, {@link
|
||||
* InstanceMethodsInterceptV2Point} and {@link StaticMethodsInterceptV2Point} If plugin is going to enhance constructors,
|
||||
* instance methods, or both, {@link ClassEnhancePluginDefineV2} will add a field of {@link Object} type.
|
||||
*/
|
||||
public abstract class ClassEnhancePluginDefineV2 extends AbstractClassEnhancePluginDefine {
|
||||
|
||||
@Override
|
||||
protected DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException {
|
||||
StaticMethodsInterceptV2Point[] staticMethodsInterceptV2Points = getStaticMethodsInterceptV2Points();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
if (staticMethodsInterceptV2Points == null || staticMethodsInterceptV2Points.length == 0) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
for (StaticMethodsInterceptV2Point staticMethodsInterceptV2Point : staticMethodsInterceptV2Points) {
|
||||
String interceptor = staticMethodsInterceptV2Point.getMethodsInterceptorV2();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException(
|
||||
"no StaticMethodsAroundInterceptorV2 define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
|
||||
if (staticMethodsInterceptV2Point.isOverrideArgs()) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(new StaticMethodsInterV2WithOverrideArgs(interceptor)));
|
||||
}
|
||||
} else {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new StaticMethodsInterV2(interceptor)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException {
|
||||
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
|
||||
InstanceMethodsInterceptV2Point[] instanceMethodsInterceptV2Points = getInstanceMethodsInterceptV2Points();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
|
||||
boolean existedConstructorInterceptPoint = false;
|
||||
if (constructorInterceptPoints != null && constructorInterceptPoints.length > 0) {
|
||||
existedConstructorInterceptPoint = true;
|
||||
}
|
||||
boolean existedMethodsInterceptV2Points = false;
|
||||
if (instanceMethodsInterceptV2Points != null && instanceMethodsInterceptV2Points.length > 0) {
|
||||
existedMethodsInterceptV2Points = true;
|
||||
}
|
||||
|
||||
if (!existedConstructorInterceptPoint && !existedMethodsInterceptV2Points) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
if (!typeDescription.isAssignableTo(EnhancedInstance.class)) {
|
||||
if (!context.isObjectExtended()) {
|
||||
newClassBuilder = newClassBuilder.defineField(
|
||||
CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE)
|
||||
.implement(EnhancedInstance.class)
|
||||
.intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME));
|
||||
context.extendObjectCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
if (existedConstructorInterceptPoint) {
|
||||
for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher())
|
||||
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost
|
||||
.forInternalDelegateClass(constructorInterceptPoint
|
||||
.getConstructorInterceptor()))));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher())
|
||||
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new ConstructorInter(constructorInterceptPoint
|
||||
.getConstructorInterceptor(), classLoader))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (existedMethodsInterceptV2Points) {
|
||||
for (InstanceMethodsInterceptV2Point instanceMethodsInterceptV2Point : instanceMethodsInterceptV2Points) {
|
||||
String interceptor = instanceMethodsInterceptV2Point.getMethodsInterceptorV2();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException(
|
||||
"no InstanceMethodsAroundInterceptorV2 define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(
|
||||
instanceMethodsInterceptV2Point.getMethodsMatcher());
|
||||
if (instanceMethodsInterceptV2Point instanceof DeclaredInstanceMethodsInterceptV2Point) {
|
||||
junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
|
||||
}
|
||||
if (instanceMethodsInterceptV2Point.isOverrideArgs()) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(new InstMethodsInterV2WithOverrideArgs(interceptor, classLoader)));
|
||||
}
|
||||
} else {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(junction)
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new InstMethodsInterV2(interceptor, classLoader)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,37 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class instance methods. Actually, inherit from {@link
|
||||
* ClassInstanceMethodsEnhancePluginDefineV2} has no differences with inherit from {@link ClassEnhancePluginDefineV2}.
|
||||
* Just override {@link ClassEnhancePluginDefineV2#getStaticMethodsInterceptPoints}, and return NULL, which means nothing
|
||||
* to enhance.
|
||||
*/
|
||||
public abstract class ClassInstanceMethodsEnhancePluginDefineV2 extends ClassEnhancePluginDefineV2 {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 static methods.
|
||||
*/
|
||||
@Override
|
||||
public StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class static methods. Actually, inherit from {@link
|
||||
* ClassStaticMethodsEnhancePluginDefineV2} has no differences with inherit from {@link ClassEnhancePluginDefineV2}. Just
|
||||
* override {@link ClassEnhancePluginDefineV2#getConstructorsInterceptPoints} and {@link
|
||||
* ClassEnhancePluginDefineV2#getInstanceMethodsInterceptV2Points}, and return NULL, which means nothing to enhance.
|
||||
*/
|
||||
public abstract class ClassStaticMethodsEnhancePluginDefineV2 extends ClassEnhancePluginDefineV2 {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no constructors.
|
||||
*/
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 instance methods.
|
||||
*/
|
||||
@Override
|
||||
public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,87 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInterV2 {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2.class);
|
||||
|
||||
private InstanceMethodsAroundInterceptorV2 interceptor;
|
||||
|
||||
public InstMethodsInterV2(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1,106 +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 cn.hippo4j.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import cn.hippo4j.common.logging.api.ILog;
|
||||
import cn.hippo4j.common.logging.api.LogManager;
|
||||
import cn.hippo4j.agent.core.plugin.PluginException;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import cn.hippo4j.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInterV2WithOverrideArgs {
|
||||
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2WithOverrideArgs.class);
|
||||
|
||||
/**
|
||||
* An {@link InstanceMethodsAroundInterceptorV2} This name should only stay in {@link String}, the real {@link Class}
|
||||
* type will trigger classloader failure. If you want to know more, please check on books about Classloader or
|
||||
* Classloader appointment mechanism.
|
||||
*/
|
||||
private InstanceMethodsAroundInterceptorV2 interceptor;
|
||||
|
||||
/**
|
||||
* @param instanceMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public InstMethodsInterV2WithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue