├── .gitignore
├── CONTRIBUTING.md
├── LEGAL.md
├── LICENSE
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── ps-bootstrap
├── .gitignore
├── desc_tar.xml
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── alipay
│ │ │ └── antchain
│ │ │ └── bridge
│ │ │ └── pluginserver
│ │ │ ├── AntChainBridgePluginServerApplication.java
│ │ │ └── config
│ │ │ └── PluginManagerConfiguration.java
│ └── resources
│ │ ├── application.yml
│ │ ├── banner.txt
│ │ ├── logback-spring.xml
│ │ └── scripts
│ │ ├── init_tls_certs.sh
│ │ ├── plugin-server.service
│ │ ├── print.sh
│ │ ├── start.sh
│ │ └── stop.sh
│ └── test
│ ├── java
│ └── com
│ │ └── alipay
│ │ └── antchain
│ │ └── bridge
│ │ └── pluginserver
│ │ ├── AntChainBridgePluginManagementApplicationTests.java
│ │ └── AntChainBridgePluginServerApplicationTests.java
│ └── resources
│ ├── application.yml
│ └── logback-spring.xml
├── ps-cli
├── .gitignore
├── README.md
├── desc_tar.xml
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── alipay
│ │ └── antchain
│ │ └── bridge
│ │ └── pluginserver
│ │ └── cli
│ │ ├── command
│ │ ├── ArgsConstraint.java
│ │ ├── Command.java
│ │ ├── CommandHandler.java
│ │ ├── CommandNamespace.java
│ │ ├── CommandNamespaceImpl.java
│ │ ├── ManagementCommandNamespace.java
│ │ ├── NamespaceManager.java
│ │ └── NamespaceManagerImpl.java
│ │ ├── core
│ │ └── ManagementGrpcClient.java
│ │ └── shell
│ │ ├── GlLineReader.java
│ │ ├── GroovyScriptCommandNamespace.java
│ │ ├── GroovyShellProvider.java
│ │ ├── JsonUtil.java
│ │ ├── Launcher.java
│ │ ├── PromptCompleter.java
│ │ ├── ReservedWord.java
│ │ ├── Shell.java
│ │ └── ShellProvider.java
│ └── resources
│ ├── VERSION
│ ├── logback.xml
│ └── scripts
│ └── start.sh
├── ps-pluginmanager
├── .gitignore
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── alipay
│ └── antchain
│ └── bridge
│ └── pluginserver
│ └── pluginmanager
│ ├── IPluginManagerWrapper.java
│ └── PluginManagerWrapperImpl.java
├── ps-server
├── .gitignore
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── alipay
│ └── antchain
│ └── bridge
│ └── pluginserver
│ └── server
│ ├── CrossChainServiceImpl.java
│ ├── PluginManagementServiceImpl.java
│ ├── ResponseBuilder.java
│ ├── exception
│ └── ServerErrorCodeEnum.java
│ └── interceptor
│ └── RequestTraceInterceptor.java
└── ps-service
├── .gitignore
├── pom.xml
└── src
└── main
└── proto
├── managementserver.proto
└── pluginserver.proto
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 | replay_pid*
25 |
26 | .idea
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 |
3 | ## Branch Strategy
4 |
5 | We recommend that developers following the rules [here](https://jeffkreeftmeijer.com/git-flow/git-flow.png).
6 |
7 | - Branch `main` with stable code and tags on it.
8 | - Branch `develop` for "next release" development.
9 | - Feature branches start with prefix `feat/`
10 | - Release branches start with prefix `release/`
11 | - Hotfix branches start with prefix `hotfix/`
12 |
13 | ## Contributing
14 |
15 | - Fork the repository or create branches.
16 | - Checkout your branch like a feature or bugfix.
17 | - Make a pull request to the `develop` branch of this repository.
18 | - Wait for review and PR merged.
19 |
20 | ---
21 |
22 | **Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://kcd.im/pull-request)
--------------------------------------------------------------------------------
/LEGAL.md:
--------------------------------------------------------------------------------
1 | Legal Disclaimer
2 |
3 | Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail.
4 |
5 | 法律免责声明
6 |
7 | 关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
19 |
20 | > [!CAUTION]
21 | > 本仓库已经废弃,请转到[AntChainBridge](https://github.com/AntChainOpenLabs/AntChainBridge)
22 |
23 | # 介绍
24 |
25 | AntChain Bridge 插件服务(PluginServer, PS)用于管理异构链插件、完成与中继通信的工作。
26 |
27 | - **插件管理能力**
28 |
29 | 在开发者完成一个异构链插件开发之后,将该插件打包放到PS的指定路径之下,启动PS即可加载该插件,PS将完成插件和区块链桥接组件(Blockchain Bridge Component, BBC)对象的管理等工作,PS还提供了CLI工具完成诸如插件重新加载、停止等工作。
30 |
31 | - **与中继通信**
32 |
33 | 将PS注册到一个中继之后,PS会作为一个RPC Server为中继提供服务,PS和中继之间会建立双向认证的TLS连接,确保身份互认和安全性,中继会发送请求要求PS完成BBC对象初始化等工作,并调用BBC的接口,完成与异构链的交互。
34 |
35 | # 架构
36 |
37 | 下面介绍了中继服务的整体架构。
38 |
39 | **以下插件BCOS和插件ChainMaker均为展示用例,代表不同的异构插件实现*
40 |
41 |
42 |
43 | # 快速开始
44 |
45 | ## 构建
46 |
47 | 进入代码的根目录,运行mvn编译即可:
48 |
49 | ```shell
50 | mvn clean package
51 | ```
52 |
53 | 产生的安装包在`ps-bootstrap/target/plugin-server-x.x.x.tar.gz`。
54 |
55 | ## 配置
56 |
57 | 在获得安装包之后,执行解压缩操作,这里以`plugin-server-x.x.x.tar.gz`为例。
58 |
59 | ```
60 | tar -zxf plugin-server-x.x.x.tar.gz
61 | ```
62 |
63 | 进入解压后的目录,可以看到:
64 |
65 | ```
66 | cd plugin-server/
67 | tree .
68 | .
69 | ├── README.md
70 | ├── bin
71 | │ ├── init_tls_certs.sh
72 | │ ├── plugin-server.service
73 | │ ├── print.sh
74 | │ ├── start.sh
75 | │ └── stop.sh
76 | ├── config
77 | │ └── application.yml
78 | └── lib
79 | └── ps-bootstrap-x.x.x.jar
80 |
81 |
82 | 3 directories, 8 files
83 | ```
84 |
85 | 首先,初始化PS的TLS秘钥和证书,该脚本将会在项目根目录下创建文件夹`certs`,下面存储了私钥`server.key`、证书`server.crt`、信任的证书`trust.crt`。
86 |
87 | ```
88 | ./bin/init_tls_certs.sh
89 | ```
90 |
91 | 然后,在和中继建立连接之前,中继的运维人员应该将中继的证书发送给了您,比如`relayer.crt`,您需要将这个证书添加到`trust.crt`中。
92 |
93 | ```
94 | cat relayer.crt >> trust.crt
95 | ```
96 |
97 | 最后修改您的配置文件,将证书目录配置进去。
98 |
99 | ```
100 | vi config/application.yml
101 | ```
102 |
103 | 依次替换`grpc.server.security.certificate-chain`、`grpc.server.security.private-key`和`grpc.server.security.trustCertCollection`的配置项。
104 | 下面给出一个例子,示例中诸如`/path/to/certs/server.crt`的具体配置属性值请替换为您的实际路径,`file:`保留:
105 |
106 | ```yaml
107 | grpc:
108 | server:
109 | security:
110 | # server certificate
111 | certificate-chain: file:/path/to/certs/server.crt
112 | # server key
113 | private-key: file:/path/to/certs/server.key
114 | # Mutual Certificate Authentication
115 | trustCertCollection: file:/path/to/certs/trust.crt
116 | ```
117 |
118 | 然后修改插件库路径,PS将加载这个路径下的插件。修改配置项`pluginserver.plugin.repo`,比如:
119 |
120 | ```yaml
121 | pluginserver:
122 | plugin:
123 | # where to load the hetero-chain plugins
124 | repo: /path/to/plugins
125 | ```
126 |
127 | 将您的插件都放到这个路径下即可。
128 |
129 | ## 运行
130 |
131 | ### 作为系统服务运行
132 |
133 | 在解压包根目录之下,可以找到`start.sh`脚本。
134 |
135 | 如下可以打印帮助信息:
136 |
137 | ```
138 | ./bin/start.sh -h
139 |
140 | start.sh — Start the plugin server
141 |
142 | Usage:
143 | start.sh
144 |
145 | Examples:
146 | 1. start in system service mode:
147 | start.sh -s
148 | 2. start in application mode:
149 | start.sh
150 |
151 | Options:
152 | -s run in system service mode.
153 | -h print help information.
154 | ```
155 |
156 | 运行如下命令,会自动将插件服务启动为系统服务:
157 |
158 | ```
159 | ./bin/start.sh -s
160 | ```
161 |
162 | 看到下面的输出即启动成功:
163 |
164 | ```
165 | ___ __ ______ __ _ ____ _ __
166 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
167 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
168 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
169 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
170 | /____/
171 |
172 | [ INFO ]_[ 2023-06-20 20:57:06.168 ] : running in system service mode
173 | [ INFO ]_[ 2023-06-20 20:57:06.168 ] : plugin-server started successfully
174 | ```
175 |
176 | 可以通过下面命令查看系统服务状态:
177 |
178 | ```
179 | systemctl status plugin-server.service
180 | ```
181 |
182 | ### 作为普通进程运行
183 |
184 | 在解压包根目录之下,运行一下命令即可:
185 |
186 | ```
187 | ./bin/start.sh
188 | ```
189 |
190 | 看到下面的输出即启动成功:
191 |
192 | ```
193 | ___ __ ______ __ _ ____ _ __
194 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
195 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
196 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
197 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
198 | /____/
199 |
200 | [ INFO ]_[ 2023-03-30 15:11:27.1680160287 ] : start plugin-server now...
201 | [ INFO ]_[ 2023-03-30 15:11:27.1680160287 ] : plugin-server started successfully
202 | ```
203 |
204 | 可以通过`bin/stop.sh`关闭服务。
205 |
206 | 日志文件存储在`log`目录之下。
207 |
208 | ## 插件
209 |
210 | 将你的插件放在配置`pluginserver.plugin.repo`的路径之下,然后启动插件服务即可加载所有插件。
211 |
212 | 插件运行中使用`BBCLogger`打印的日志,比如[这里](https://github.com/AntChainOpenLabs/AntChainBridgePluginSDK/blob/604c5b97305ee77cfa1e14454f5b99f1f905f6ea/pluginset/ethereum/offchain-plugin/src/main/java/com/alipay/antchain/bridge/plugins/ethereum/EthereumBBCService.java#L74),插件服务将会按照插件的`product`和BBCService对象的`domain`,打印到不同文件`logs/bbc/${product}/${domain}`,比如下面`product`为`simple-ethereum`和域名为`domainB`的日志文件。
213 |
214 | ```
215 | logs/
216 | ├── antchain-bridge-pluginserver
217 | │ ├── application.log
218 | │ └── error.log
219 | └── bbc
220 | └── simple-ethereum
221 | └── domainB.log
222 |
223 | 3 directories, 3 files
224 | ```
225 |
226 | ## 运行测试
227 |
228 | 在运行测试之前,请使用`ps-bootstrap/src/main/resources/scripts/init_tls_certs.sh`生成证书,并将`server.key`和`server.crt` 放到`ps-bootstrap/src/test/resources`之下,运行下述命令即可运行测试用例:
229 |
230 | ```
231 | mvn test
232 | ```
233 |
234 | # CLI
235 |
236 | CLI工具在[v0.2.0](https://github.com/AntChainOpenLab/AntChainBridgePluginServer/releases/tag/v0.2.0)版本已经发布,相关教程请参考[文档](https://github.com/AntChainOpenLab/AntChainBridgePluginServer/blob/main/ps-cli/README.md)。
237 |
238 |
239 | # 社区治理
240 |
241 | AntChain Bridge 欢迎您以任何形式参与社区建设。
242 |
243 | 您可以通过以下方式参与社区讨论
244 |
245 | - 钉钉
246 |
247 | 
248 |
249 | - 邮件
250 |
251 | 发送邮件到`antchainbridge@service.alipay.com`
252 |
253 | # License
254 |
255 | 详情参考[LICENSE](./LICENSE)。
256 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.18
9 |
10 |
11 | pom
12 |
13 | ps-bootstrap
14 | ps-service
15 | ps-server
16 | ps-pluginmanager
17 | ps-cli
18 |
19 |
20 |
21 | 8
22 | 0.2.3
23 | 2.15.0.RELEASE
24 | 2.0.59.Final
25 | 3.19.1
26 | 0.6.1
27 | 1.62.2
28 | 1.3.5
29 | 4.13.2
30 | 0.2.2
31 | 3.3.0
32 | 3.0.17
33 | 1.5.0
34 | 5.8.26
35 | 1.2.83_noneautotype
36 | 3.10.0
37 | 1.7.28
38 | 2.0.0
39 | 2.2
40 | 1.2.13
41 | ${settings.localRepository}/org/mortbay/jetty/alpn/jetty-alpn-agent/${jetty.alpnAgent.version}/jetty-alpn-agent-${jetty.alpnAgent.version}.jar
42 |
43 |
44 |
45 |
46 | github
47 | https://maven.pkg.github.com/AntChainOpenLab/*
48 |
49 | true
50 |
51 |
52 |
53 |
54 | com.alipay.antchain.bridge
55 | antchain-bridge-pluginserver
56 | 0.2.3
57 |
58 | antchain-bridge-pluginserver
59 | antchain-bridge-pluginserver
60 |
61 |
62 |
63 |
64 | net.devh
65 | grpc-server-spring-boot-starter
66 | ${grpc-starter.version}
67 |
68 |
69 | io.netty
70 | netty-tcnative-boringssl-static
71 | ${netty-tcnative-boringssl-static.version}
72 |
73 |
74 | io.grpc
75 | grpc-core
76 | ${grpc.version}
77 |
78 |
79 | io.grpc
80 | grpc-inprocess
81 | ${grpc.version}
82 |
83 |
84 | io.grpc
85 | grpc-services
86 | ${grpc.version}
87 |
88 |
89 | io.grpc
90 | grpc-api
91 | ${grpc.version}
92 |
93 |
94 | io.grpc
95 | grpc-netty-shaded
96 | ${grpc.version}
97 |
98 |
99 | io.grpc
100 | grpc-stub
101 | ${grpc.version}
102 |
103 |
104 | io.grpc
105 | grpc-protobuf
106 | ${grpc.version}
107 |
108 |
109 |
110 | jakarta.annotation
111 | jakarta.annotation-api
112 | ${jakarta.annotation-api.version}
113 | true
114 |
115 |
116 | com.alipay.antchain.bridge
117 | ps-service
118 | ${pluginserver.version}
119 |
120 |
121 | com.alipay.antchain.bridge
122 | ps-server
123 | ${pluginserver.version}
124 |
125 |
126 | com.alipay.antchain.bridge
127 | ps-pluginmanager
128 | ${pluginserver.version}
129 |
130 |
131 | com.alipay.antchain.bridge
132 | antchain-bridge-plugin-manager
133 | ${antchain-bridge.sdk.version}
134 |
135 |
136 | com.alipay.antchain.bridge
137 | antchain-bridge-spi
138 | ${antchain-bridge.sdk.version}
139 |
140 |
141 | com.alipay.antchain.bridge
142 | antchain-bridge-commons
143 | ${antchain-bridge.sdk.version}
144 |
145 |
146 | org.pf4j
147 | pf4j
148 | ${pf4j.version}
149 |
150 |
151 | com.alipay.antchain.bridge
152 | antchain-bridge-plugin-lib
153 | ${antchain-bridge.sdk.version}
154 |
155 |
156 | org.slf4j
157 | slf4j-api
158 | ${slf4j.version}
159 |
160 |
161 | org.slf4j
162 | slf4j-simple
163 | ${slf4j.version}
164 |
165 |
166 | org.jline
167 | jline
168 | ${jline.version}
169 |
170 |
171 | org.codehaus.groovy
172 | groovy-all
173 | ${groovy.version}
174 | pom
175 |
176 |
177 | commons-cli
178 | commons-cli
179 | ${commons-cli.version}
180 |
181 |
182 | cn.hutool
183 | hutool-all
184 | ${hutool.version}
185 |
186 |
187 | com.alibaba
188 | fastjson
189 | ${fastjson.version}
190 |
191 |
192 |
193 |
194 |
195 |
196 | org.yaml
197 | snakeyaml
198 | ${snake.yaml.version}
199 |
200 |
201 | ch.qos.logback
202 | logback-core
203 | ${logback.classic.version}
204 |
205 |
206 | ch.qos.logback
207 | logback-classic
208 | ${logback.classic.version}
209 |
210 |
211 | ch.qos.logback
212 | logback-core
213 |
214 |
215 |
216 |
217 |
218 | org.springframework.boot
219 | spring-boot-starter
220 |
221 |
222 | org.yaml
223 | snakeyaml
224 |
225 |
226 | ch.qos.logback
227 | logback-classic
228 |
229 |
230 |
231 |
232 | org.projectlombok
233 | lombok
234 | true
235 |
236 |
237 | org.springframework.boot
238 | spring-boot-starter-test
239 | test
240 |
241 |
242 |
243 |
244 |
245 |
246 | org.apache.maven.plugins
247 | maven-compiler-plugin
248 | ${maven-compiler-plugin.version}
249 |
250 | ${java.version}
251 | ${java.version}
252 | UTF-8
253 | -XDignore.symbol.file
254 |
255 |
256 |
257 | org.apache.maven.plugins
258 | maven-source-plugin
259 | ${maven-source-plugin.version}
260 |
261 |
262 | attach-sources
263 |
264 | jar-no-fork
265 |
266 |
267 |
268 |
269 |
270 | org.apache.maven.plugins
271 | maven-surefire-plugin
272 | 3.0.0-M5
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
--------------------------------------------------------------------------------
/ps-bootstrap/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
--------------------------------------------------------------------------------
/ps-bootstrap/desc_tar.xml:
--------------------------------------------------------------------------------
1 |
4 | ${version}
5 |
6 | tar.gz
7 |
8 | true
9 |
10 |
11 | ${project.basedir}/../target/boot
12 | ${file.separator}lib
13 |
14 | ${artifactId}-${version}.jar
15 |
16 |
17 |
18 | ${project.basedir}/src/main/resources/scripts
19 | ${file.separator}bin
20 |
21 | *.sh
22 | plugin-server.service
23 |
24 |
25 |
26 | ${project.basedir}/src/main/resources
27 | ${file.separator}config
28 |
29 | application.yml
30 |
31 |
32 |
33 | ${project.basedir}/../
34 | ${file.separator}
35 |
36 | README.md
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/ps-bootstrap/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.alipay.antchain.bridge
8 | antchain-bridge-pluginserver
9 | 0.2.3
10 |
11 |
12 | ps-bootstrap
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | com.alipay.antchain.bridge
23 | ps-server
24 |
25 |
26 | com.alipay.antchain.bridge
27 | ps-pluginmanager
28 |
29 |
30 |
31 |
32 |
33 |
34 | src/main/resources
35 |
36 | **/application.yml
37 | **/*.xml
38 | **/banner.txt
39 |
40 |
41 | true
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-deploy-plugin
48 | 2.7
49 |
50 | true
51 |
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-maven-plugin
56 |
57 |
58 |
59 | org.projectlombok
60 | lombok
61 |
62 |
63 | ../target/boot
64 |
65 |
66 |
67 |
68 | repackage
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-resources-plugin
76 |
77 |
78 | jks
79 |
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-assembly-plugin
85 | 3.1.0
86 |
87 |
88 |
89 | plugin-server
90 |
91 | desc_tar.xml
92 |
93 |
94 | make-tar
95 | package
96 |
97 | single
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/java/com/alipay/antchain/bridge/pluginserver/AntChainBridgePluginServerApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver;
18 |
19 | import org.springframework.boot.WebApplicationType;
20 | import org.springframework.boot.autoconfigure.SpringBootApplication;
21 | import org.springframework.boot.builder.SpringApplicationBuilder;
22 |
23 | @SpringBootApplication(scanBasePackages = {"com.alipay.antchain.bridge.pluginserver"})
24 | public class AntChainBridgePluginServerApplication {
25 |
26 | public static void main(String[] args) {
27 | new SpringApplicationBuilder(AntChainBridgePluginServerApplication.class)
28 | .web(WebApplicationType.NONE)
29 | .run(args);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/java/com/alipay/antchain/bridge/pluginserver/config/PluginManagerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.config;
18 |
19 | import java.io.IOException;
20 | import java.net.InetAddress;
21 | import java.net.InetSocketAddress;
22 |
23 | import cn.hutool.core.util.StrUtil;
24 | import com.alipay.antchain.bridge.pluginserver.server.PluginManagementServiceImpl;
25 | import io.grpc.Server;
26 | import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
27 | import lombok.extern.slf4j.Slf4j;
28 | import org.springframework.beans.factory.annotation.Autowired;
29 | import org.springframework.beans.factory.annotation.Value;
30 | import org.springframework.context.annotation.Bean;
31 | import org.springframework.context.annotation.Configuration;
32 |
33 | @Configuration
34 | @Slf4j
35 | public class PluginManagerConfiguration {
36 |
37 | @Value("${pluginserver.managerserver.host:localhost}")
38 | private String managementHost;
39 |
40 | @Value("${pluginserver.managerserver.port}")
41 | private String pluginServerMgrPort;
42 |
43 | @Bean
44 | public Server pluginMgrServer(@Autowired PluginManagementServiceImpl pluginManagementService) throws IOException {
45 | log.info("Starting plugin managing server on port " + pluginServerMgrPort);
46 | return NettyServerBuilder.forAddress(
47 | new InetSocketAddress(
48 | StrUtil.isEmpty(managementHost) ? InetAddress.getLoopbackAddress() : InetAddress.getByName(managementHost),
49 | Integer.parseInt(pluginServerMgrPort)
50 | )
51 | ).addService(pluginManagementService)
52 | .build()
53 | .start();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: antchain-bridge-pluginserver
4 |
5 | logging:
6 | file:
7 | path: ./logs
8 |
9 | # here to configure grpc settings for the plugin server
10 | grpc:
11 | server:
12 | address: 0.0.0.0
13 | port: 9090
14 | security:
15 | # enable tls mode
16 | enabled: true
17 | # server certificate
18 | certificate-chain: file:certs/server.crt
19 | # server key
20 | private-key: file:certs/server.key
21 | # Mutual Certificate Authentication
22 | trustCertCollection: file:certs/trust.crt
23 | clientAuth: REQUIRE
24 |
25 | # settings about plugin-server
26 | pluginserver:
27 | plugin:
28 | # where to load the hetero-chain plugins
29 | repo: ./plugins
30 | policy:
31 | # limit actions of the plugin classloader
32 | classloader:
33 | resource:
34 | ban-with-prefix:
35 | # the plugin classloader will not read the resource file starting with the prefix below
36 | APPLICATION: "META-INF/services/io.grpc."
37 | managerserver:
38 | host: localhost
39 | port: 9091
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ${AnsiColor.BLUE}${AnsiStyle.BOLD}
2 | ___ __ ______ __ _ ____ _ __
3 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
4 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
5 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
6 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
7 | /____/
8 | plugin-server @project.version@
9 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ${logging.path}/${APP_NAME}/error.log
16 |
17 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
18 | %msg%n
19 |
20 | UTF-8
21 |
22 |
23 | ${logging.path}/${APP_NAME}/error.log.%d{yyyy-MM-dd}.%i
24 | 7
25 | 100MB
26 | 2GB
27 |
28 |
29 | ERROR
30 | ACCEPT
31 | DENY
32 |
33 |
34 |
35 |
36 | 0
37 |
38 | 512
39 |
40 |
41 |
42 |
43 |
44 |
45 | ${logging.path}/${APP_NAME}/application.log
46 |
47 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
48 | %msg%n
49 |
50 | UTF-8
51 |
52 |
53 | ${logging.path}/${APP_NAME}/application.log.%d{yyyy-MM-dd}.%i
54 | 7
55 | 50MB
56 | 2GB
57 | true
58 |
59 |
60 | ERROR
61 | DENY
62 | ACCEPT
63 |
64 |
65 |
66 |
67 | 0
68 |
69 | 512
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
80 |
81 |
82 |
83 | INFO
84 |
85 |
86 |
87 |
88 |
89 | ${logging.path}/${APP_NAME}/req_trace.log
90 |
91 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
92 | %msg%n
93 |
94 | UTF-8
95 |
96 |
97 | ${logging.path}/${APP_NAME}/req_trace.log.%d{yyyy-MM-dd}.%i
98 | 7
99 | 50MB
100 | 500MB
101 | true
102 |
103 |
104 |
105 |
106 | 0
107 |
108 | 256
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/scripts/init_tls_certs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Copyright 2023 Ant Group
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | CURR_DIR="$(cd `dirname $0`; pwd)"
20 | source ${CURR_DIR}/print.sh
21 |
22 | print_title
23 |
24 | if [ ! -d ${CURR_DIR}/../certs ]; then
25 | mkdir -p ${CURR_DIR}/../certs
26 | fi
27 |
28 | openssl genrsa -out ${CURR_DIR}/../certs/server.key 2048 > /dev/null 2>&1
29 | if [ $? -ne 0 ]; then
30 | log_error "failed to generate server.key"
31 | exit 1
32 | fi
33 | openssl pkcs8 -topk8 -inform pem -in ${CURR_DIR}/../certs/server.key -nocrypt -out ${CURR_DIR}/../certs/server_pkcs8.key
34 | if [ $? -ne 0 ]; then
35 | log_error "failed to generate pkcs8 server.key"
36 | exit 1
37 | fi
38 | mv ${CURR_DIR}/../certs/server_pkcs8.key ${CURR_DIR}/../certs/server.key
39 | log_info "generate server.key successfully"
40 |
41 | openssl req -new -x509 -days 36500 -key ${CURR_DIR}/../certs/server.key -out ${CURR_DIR}/../certs/server.crt -subj "/C=CN/ST=mykey/L=mykey/O=mykey/OU=mykey/CN=pluginserver"
42 | if [ $? -ne 0 ]; then
43 | log_error "failed to generate server.crt"
44 | exit 1
45 | fi
46 | log_info "generate server.crt successfully"
47 |
48 | if [ ! -f "trust.crt" ]; then
49 | cp ${CURR_DIR}/../certs/server.crt ${CURR_DIR}/../certs/trust.crt
50 | log_info "generate trust.crt successfully"
51 | fi
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/scripts/plugin-server.service:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2023 Ant Group
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | [Unit]
18 | Description=start shell script
19 | StartLimitIntervalSec=0
20 |
21 | [Service]
22 | ExecStart=@@START_CMD@@
23 | Restart=always
24 | RestartSec=5
25 | WorkingDirectory=@@WORKING_DIR@@
26 |
27 | [Install]
28 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/scripts/print.sh:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2023 Ant Group
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | RED='\033[0;31m'
18 | GREEN='\033[0;32m'
19 | BLUE='\033[0;34m'
20 | YELLOW='\033[1;33m'
21 | WHITE='\033[1;37m'
22 | NC='\033[0m'
23 | LIGHT_GRAY='\033[0;37m'
24 |
25 | function print_blue() {
26 | printf "${BLUE}%s${NC}\n" "$1"
27 | }
28 |
29 | function print_red() {
30 | printf "${RED}%s${NC}\n" "$1"
31 | }
32 |
33 | function print_green() {
34 | printf "${GREEN}%s${NC}\n" "$1"
35 | }
36 |
37 | function print_hint() {
38 | printf "${WHITE}\033[4m%s${NC}" "$1"
39 | }
40 |
41 | function log_info() {
42 | NOW=$(date "+%Y-%m-%d %H:%M:%S.%s" | cut -b 1-23)
43 | INFO_PREFIX=$(printf "${GREEN}\033[4m[ INFO ]${NC}")
44 |
45 | INFO=$(printf "_${LIGHT_GRAY}[ %s ]${NC} : %s" "${NOW}" "$1")
46 | echo "${INFO_PREFIX}${INFO}"
47 | }
48 |
49 | function log_warn() {
50 | NOW=$(date "+%Y-%m-%d %H:%M:%S.%s" | cut -b 1-23)
51 | WARN_PREFIX=$(printf "${YELLOW}\033[4m[ WARN ]${NC}")
52 |
53 | INFO=$(printf "_${LIGHT_GRAY}[ %s ]${NC} : %s" "${NOW}" "$1")
54 | echo "${WARN_PREFIX}${INFO}"
55 | }
56 |
57 | function log_error() {
58 | NOW=$(date "+%Y-%m-%d %H:%M:%S.%s" | cut -b 1-23)
59 | ERROR_PREFIX=$(printf "${RED}\033[4m[ ERROR ]${NC}")
60 |
61 | INFO=$(printf "_${LIGHT_GRAY}[ %s ]${NC} : %s" "${NOW}" "$1")
62 | echo "${ERROR_PREFIX}${INFO}"
63 | }
64 |
65 | function print_title() {
66 | echo ' ___ __ ______ __ _ ____ _ __'
67 | echo ' / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___'
68 | echo ' / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \'
69 | echo ' / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/'
70 | echo '/_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/'
71 | echo ' /____/ '
72 | echo
73 | }
74 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/scripts/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Copyright 2023 Ant Group
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | Help=$(
20 | cat <<-"HELP"
21 |
22 | start.sh — Start the plugin server
23 |
24 | Usage:
25 | start.sh
26 |
27 | Examples:
28 | 1. start in system service mode:
29 | start.sh -s
30 | 2. start in application mode:
31 | start.sh
32 |
33 | Options:
34 | -s run in system service mode.
35 | -h print help information.
36 |
37 | HELP
38 | )
39 |
40 | CURR_DIR="$(
41 | cd $(dirname $0)
42 | pwd
43 | )"
44 |
45 | while getopts "hs" opt; do
46 | case "$opt" in
47 | "h")
48 | echo "$Help"
49 | exit 0
50 | ;;
51 | "s")
52 | IF_SYS_MODE="on"
53 | ;;
54 | "?")
55 | echo "invalid arguments. "
56 | exit 1
57 | ;;
58 | *)
59 | echo "Unknown error while processing options"
60 | exit 1
61 | ;;
62 | esac
63 | done
64 |
65 | source ${CURR_DIR}/print.sh
66 |
67 | print_title
68 |
69 | JAR_FILE=$(ls ${CURR_DIR}/../lib/ | grep '.jar')
70 |
71 | if [ "$IF_SYS_MODE" == "on" ]; then
72 | if [[ "$OSTYPE" == "darwin"* ]]; then
73 | log_error "${OSTYPE} not support running in system service mode"
74 | exit 1
75 | fi
76 |
77 | touch /usr/lib/systemd/system/test123 >/dev/null && rm -f /usr/lib/systemd/system/test123
78 | if [ $? -ne 0 ]; then
79 | log_error "Your account on this OS must have authority to access /usr/lib/systemd/system/"
80 | exit 1
81 | fi
82 |
83 | log_info "running in system service mode"
84 |
85 | JAVA_BIN=$(which java)
86 | if [ -z "$JAVA_BIN" ]; then
87 | log_error "install jdk before start"
88 | exit 1
89 | fi
90 | START_CMD="${JAVA_BIN} -jar -Dlogging.file.path=${CURR_DIR}/../log ${CURR_DIR}/../lib/${JAR_FILE} --spring.config.location=file:${CURR_DIR}/../config/application.yml"
91 | WORK_DIR="$(
92 | cd ${CURR_DIR}/..
93 | pwd
94 | )"
95 |
96 | sed -i -e "s#@@START_CMD@@#${START_CMD}#g" ${CURR_DIR}/plugin-server.service
97 | sed -i -e "s#@@WORKING_DIR@@#${WORK_DIR}#g" ${CURR_DIR}/plugin-server.service
98 |
99 | cp -f ${CURR_DIR}/plugin-server.service /usr/lib/systemd/system/
100 | if [ $? -ne 0 ]; then
101 | log_error "failed to cp plugin-server.service to /usr/lib/systemd/system/"
102 | exit 1
103 | fi
104 |
105 | systemctl daemon-reload && systemctl enable plugin-server.service
106 | if [ $? -ne 0 ]; then
107 | log_error "failed to enable plugin-server.service"
108 | exit 1
109 | fi
110 |
111 | systemctl start plugin-server
112 | if [ $? -ne 0 ]; then
113 | log_error "failed to start plugin-server.service"
114 | exit 1
115 | fi
116 |
117 | else
118 | log_info "running in app mode"
119 | log_info "start plugin-server now..."
120 |
121 | cd ${CURR_DIR}/..
122 | java -jar -Dlogging.file.path=${CURR_DIR}/../log ${CURR_DIR}/../lib/${JAR_FILE} --spring.config.location=file:${CURR_DIR}/../config/application.yml >/dev/null 2>&1 &
123 | if [ $? -ne 0 ]; then
124 | log_error "failed to start plugin-server"
125 | exit 1
126 | fi
127 | fi
128 |
129 | log_info "plugin-server started successfully"
130 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/main/resources/scripts/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Copyright 2023 Ant Group
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | CURR_DIR="$(
20 | cd $(dirname $0)
21 | pwd
22 | )"
23 | source ${CURR_DIR}/print.sh
24 |
25 | print_title
26 |
27 | log_info "stop plugin-server now..."
28 |
29 | ps -ewf | grep -e "ps-bootstrap.*\.jar" | grep -v grep | awk '{print $2}' | xargs kill
30 | if [ $? -ne 0 ]; then
31 | log_error "failed to stop plugin-server"
32 | exit 1
33 | fi
34 |
35 | log_info "plugin-server stopped successfully"
36 |
--------------------------------------------------------------------------------
/ps-bootstrap/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: antchain-bridge-pluginserver
4 | profiles:
5 | active: dev
6 |
7 | logging:
8 | file:
9 | path: ./logs
10 |
11 | grpc:
12 | server:
13 | address: 0.0.0.0
14 | port: 9090
15 | security:
16 | # enable tls mode
17 | enabled: true
18 | # server certificate
19 | certificate-chain: classpath:server.crt
20 | # server key
21 | private-key: classpath:server.key
22 | # Mutual Certificate Authentication
23 | trustCertCollection: classpath:server.crt
24 | clientAuth: REQUIRE
25 |
26 | pluginserver:
27 | plugin:
28 | repo: src/test/resources/defaultPlugins
29 | policy:
30 | classloader:
31 | resource:
32 | ban-with-prefix:
33 | APPLICATION: "META-INF/services/io.grpc."
34 | managerserver:
35 | host: 0.0.0.0
36 | port: 9091
--------------------------------------------------------------------------------
/ps-bootstrap/src/test/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ${logging.path}/${APP_NAME}/error.log
16 |
17 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
18 | %msg%n
19 |
20 | UTF-8
21 |
22 |
23 | ${logging.path}/${APP_NAME}/error.log.%d{yyyy-MM-dd}.%i
24 | 7
25 | 100MB
26 | 2GB
27 |
28 |
29 | ERROR
30 | ACCEPT
31 | DENY
32 |
33 |
34 |
35 |
36 | 0
37 |
38 | 512
39 |
40 |
41 |
42 |
43 |
44 |
45 | ${logging.path}/${APP_NAME}/application.log
46 |
47 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
48 | %msg%n
49 |
50 | UTF-8
51 |
52 |
53 | ${logging.path}/${APP_NAME}/application.log.%d{yyyy-MM-dd}.%i
54 | 7
55 | 50MB
56 | 2GB
57 | true
58 |
59 |
60 | ERROR
61 | DENY
62 | ACCEPT
63 |
64 |
65 |
66 |
67 | 0
68 |
69 | 512
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
80 |
81 |
82 |
83 | INFO
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ps-cli/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
--------------------------------------------------------------------------------
/ps-cli/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
AntChain Bridge Plugin Server CLI
4 |
5 |
6 | ## 介绍
7 |
8 | 为了帮助管理插件服务,我们提供一个命令行工具(Command-Line Interface, CLI),帮助进行一些插件服务的运维和管理工作,比如更新插件的之后,可以通过CLI重新加载插件。
9 |
10 | ## 快速开始
11 |
12 | ### 编译
13 |
14 | 在编译插件服务的时候,会同时编译CLI。在插件服务项目的根目录下,执行:
15 |
16 | ```
17 | mvn clean package
18 | ```
19 |
20 | 编译之后,压缩包在路径`ps-cli/target/`之下。
21 |
22 | 当然,也可以在[release](https://github.com/AntChainOpenLab/AntChainBridgePluginServer/releases)页面下载安装包。
23 |
24 | ### 运行
25 |
26 | 首先,解压安装包,这里以`plugin-server-cli-0.2.0.tar.gz`为例。
27 |
28 | ```
29 | tar -zxf plugin-server-cli-0.2.0.tar.gz
30 | ```
31 |
32 | 然后,进入文件夹`plugin-server-cli`,文件结构如下:
33 |
34 | ```
35 | .
36 | ├── README.md
37 | ├── bin
38 | │ └── start.sh
39 | └── lib
40 | └── ps-cli-0.2.0.jar
41 |
42 | 2 directories, 3 files
43 | ```
44 |
45 | 通过运行`bin/start.sh -h`可以打印帮助信息,查看脚本使用方式:
46 |
47 | ```
48 | ╰─± bin/start.sh -h
49 |
50 | start.sh — Start the CLI tool to manage your plugin server
51 |
52 | Usage:
53 | start.sh
54 |
55 | Examples:
56 | 1. print help info:
57 | start.sh -h
58 | 2. identify the port number to start CLI
59 | start.sh -p 9091
60 | 3. identify the server IP to start CLI
61 | start.sh -H 0.0.0.0
62 |
63 | Options:
64 | -h print help info
65 | -p identify the port number to start CLI, default 9091
66 | -H identify the server IP to start CLI, default 0.0.0.0
67 |
68 | ```
69 |
70 | 运行`bin/start.sh`以启动CLI,按下Tab键可以补全命令。
71 |
72 | ### 使用
73 |
74 | #### 重新加载插件
75 |
76 | 场景:让插件服务,重新加载某个类型的插件。如果你修改了插件逻辑并重新编译,将插件的Jar包拷贝并覆盖原有文件,运行命令,插件服务会重新加载新的插件文件。
77 |
78 | 命令:`manage.reloadPlugin(String product)`
79 |
80 | 参数:参数`product`为插件中设置的区块链类型,比如我们提供的插件[demo](https://github.com/AntChainOpenLab/AntChainBridgePluginSDK/blob/df28f973a6f0ebdf204b86c2e49aa1be8f8d0c0c/pluginset/ethereum/offchain-plugin/src/main/java/com/alipay/antchain/bridge/plugins/ethereum/EthereumBBCService.java#L57)中的`simple-ethereum`。
81 |
82 | ```
83 | ___ __ ______ __ _ ____ _ __
84 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
85 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
86 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
87 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
88 | /____/
89 | PLUGIN SERVER CLI 0.2.0
90 |
91 | >>> type help to see all commands...
92 | ps>
93 | ps> manage.reloadPlugin("simple-ethereum")
94 | ```
95 |
96 | #### 在新路径重新加载插件
97 |
98 | 场景:让插件服务,在一个新路径重新加载某个类型的插件。如果你修改了插件逻辑并重新编译,指定新的插件文件路径,运行命令,插件服务会重新加载新的插件文件。
99 |
100 | 命令:`manage.reloadPluginInNewPath(String product, String path)`
101 |
102 | 参数:参数`product`为插件中设置的区块链类型;参数`path`指定新的插件文件路径;
103 |
104 | ```
105 | ___ __ ______ __ _ ____ _ __
106 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
107 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
108 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
109 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
110 | /____/
111 | PLUGIN SERVER CLI 0.2.0
112 |
113 | >>> type help to see all commands...
114 | ps>
115 | ps> manage.reloadPluginInNewPath("simple-ethereum", "path/to/new/simple-ethereum-bbc-0.1-SNAPSHOT-plugin.jar")
116 | ```
117 |
118 | #### 重启BBC实例
119 |
120 | 场景:当中继请求插件服务为某条链启动BBC实例之后,插件服务会从插件中读取相关Class,创建BBC实例,而更新了插件代码,经过插件的reload之后,需要重启BBC实例,才可以使用更新之后的代码提供服务。
121 |
122 | 命令:`manage.restartBBC(String product, String domain)`
123 |
124 | 参数:参数`product`为插件中设置的区块链类型;参数`domain`是你想让插件服务重新创建的BBC实例;
125 |
126 | ```
127 | ___ __ ______ __ _ ____ _ __
128 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
129 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
130 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
131 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
132 | /____/
133 | PLUGIN SERVER CLI 0.2.0
134 |
135 | >>> type help to see all commands...
136 | ps>
137 | ps> manage.restartBBC("simple-ethereum", "domainA.eth.org")
138 | success
139 | ```
140 |
141 | #### 加载新插件
142 |
143 | 场景:让插件服务,加载一个新插件,插件的类型和ID必须没有被加载过。
144 |
145 | 命令:`manage.loadPlugin(String path)`
146 |
147 | 参数:参数`path`指定新的插件文件路径,路径是相对插件服务进程的,相对路径和绝对路径都会被判断为相等;
148 |
149 | ```
150 | ___ __ ______ __ _ ____ _ __
151 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
152 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
153 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
154 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
155 | /____/
156 | PLUGIN SERVER CLI 0.2.0
157 |
158 | >>> type help to see all commands...
159 | ps>
160 | ps> manage.loadPlugin("path/to/simple-ethereum-bbc-0.1-SNAPSHOT-plugin.jar")
161 | ```
162 |
163 | #### 启动新插件
164 |
165 | 场景:让插件服务,启动一个新加载的插件(重新加载的不需要),**只有启动之后的插件才可以用于创建BBC对象**。
166 |
167 | 命令:`manage.startPlugin(String path)`
168 |
169 | 参数:参数`path`指定该插件文件路径,路径是相对插件服务进程的,相对路径和绝对路径都会被判断为相等;
170 |
171 | ```
172 | ___ __ ______ __ _ ____ _ __
173 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
174 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
175 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
176 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
177 | /____/
178 | PLUGIN SERVER CLI 0.2.0
179 |
180 | >>> type help to see all commands...
181 | ps>
182 | ps> manage.startPlugin("path/to/simple-ethereum-bbc-0.1-SNAPSHOT-plugin.jar")
183 | ```
184 |
185 | #### 停止插件
186 |
187 | 场景:让插件服务,停止使用某个插件,只有启动之后的插件才可以停止。
188 |
189 | 命令:`manage.stopPlugin(String product)`
190 |
191 | 参数:参数`product`为插件中设置的区块链类型;
192 |
193 | ```
194 | ___ __ ______ __ _ ____ _ __
195 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
196 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
197 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
198 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
199 | /____/
200 | PLUGIN SERVER CLI 0.2.0
201 |
202 | >>> type help to see all commands...
203 | ps>
204 | ps> manage.stopPlugin("simple-ethereum")
205 | ```
206 |
207 | #### 启动已停止的插件
208 |
209 | 场景:让插件服务重新启动某个已经停止的插件,只有停止之后的插件才可以重新启动。
210 |
211 | 命令:`manage.startPluginFromStop(String product)`
212 |
213 | 参数:参数`product`为插件中设置的区块链类型;
214 |
215 | ```
216 | ___ __ ______ __ _ ____ _ __
217 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
218 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
219 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
220 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
221 | /____/
222 | PLUGIN SERVER CLI 0.2.0
223 |
224 | >>> type help to see all commands...
225 | ps>
226 | ps> manage.startPluginFromStop("simple-ethereum")
227 | ```
228 |
229 | #### 查询当前所有已启动插件的类型列表
230 |
231 | 场景:让插件服务返回当前所有已经启动的插件类型列表。
232 |
233 | 命令:`manage.allPlugins()`
234 |
235 | ```
236 | ___ __ ______ __ _ ____ _ __
237 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
238 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
239 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
240 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
241 | /____/
242 | PLUGIN SERVER CLI 0.2.0
243 |
244 | >>> type help to see all commands...
245 | ps> manage.allPlugins()
246 | simple-ethereum, testchain
247 | ```
248 |
249 | #### 查询当前所有服务中的区块链域名列表
250 |
251 | 场景:让插件服务返回当前所有服务中的区块链域名列表
252 |
253 | 命令:` manage.allDomains()`
254 |
255 | ```
256 | ___ __ ______ __ _ ____ _ __
257 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
258 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
259 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
260 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
261 | /____/
262 | PLUGIN SERVER CLI 0.2.0
263 |
264 | >>> type help to see all commands...
265 | ps> manage.allDomains()
266 | chaina, chainb
267 | ```
268 |
269 | #### 查询某些区块链是否有启动的插件
270 |
271 | 场景:查询插件服务某些指定的区块链类型是否有已经启动的插件。
272 |
273 | 命令:` manage.hasPlugins(String[] products...)`
274 |
275 | 参数:`products`是区块链插件类型的数组;
276 |
277 | ```
278 | ___ __ ______ __ _ ____ _ __
279 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
280 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
281 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
282 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
283 | /____/
284 | PLUGIN SERVER CLI 0.2.0
285 |
286 | >>> type help to see all commands...
287 | ps> manage.hasPlugins("simple-ethereum", "testchain", "notexist")
288 | {
289 | "testchain":true,
290 | "notexist":false, # false 代表不存在
291 | "simple-ethereum":true # true 代表存在
292 | }
293 | ```
294 |
295 | #### 查询某些域名是否正在服务
296 |
297 | 场景:查询插件服务某些域名是否正在服务,即有正在运行的区块链BBC对象。
298 |
299 | 命令:` manage.hasDomains(String[] domains...)`
300 |
301 | 参数:`domains`是区块链插件类型的数组;
302 |
303 | ```
304 | ___ __ ______ __ _ ____ _ __
305 | / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___
306 | / /| | / __ \ / __// / / __ \ / __ `// // __ \ / __ |/ ___// // __ // __ `// _ \
307 | / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/
308 | /_/ |_|/_/ /_/ \__/ \____//_/ /_/ \__,_//_//_/ /_/ /_____//_/ /_/ \__,_/ \__, / \___/
309 | /____/
310 | PLUGIN SERVER CLI 0.2.0
311 |
312 | >>> type help to see all commands...
313 | ps> manage.hasDomains("chaina", "chainb")
314 | {
315 | "chainb":true,
316 | "chaina":false
317 | }
318 | ```
319 |
320 |
--------------------------------------------------------------------------------
/ps-cli/desc_tar.xml:
--------------------------------------------------------------------------------
1 |
4 | ${version}
5 |
6 | tar.gz
7 |
8 | true
9 |
10 |
11 | ${project.basedir}/target/boot/
12 | ${file.separator}lib
13 |
14 | ${artifactId}-${version}.jar
15 |
16 |
17 |
18 | ${project.basedir}/src/main/resources/scripts
19 | ${file.separator}bin
20 |
21 | *.sh
22 |
23 |
24 |
25 | ${project.basedir}/
26 | ${file.separator}
27 |
28 | README.md
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ps-cli/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.alipay.antchain.bridge
8 | antchain-bridge-pluginserver
9 | 0.2.3
10 |
11 |
12 | ps-cli
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | com.alipay.antchain.bridge
23 | ps-service
24 |
25 |
26 | org.jline
27 | jline
28 |
29 |
30 | org.codehaus.groovy
31 | groovy-all
32 | pom
33 |
34 |
35 | commons-cli
36 | commons-cli
37 |
38 |
39 | cn.hutool
40 | hutool-all
41 |
42 |
43 | io.grpc
44 | grpc-netty-shaded
45 |
46 |
47 | com.alibaba
48 | fastjson
49 |
50 |
51 |
52 |
53 |
54 |
55 | src/main/resources
56 |
57 | **/*.xml
58 | **/VERSION
59 |
60 |
61 | true
62 |
63 |
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-maven-plugin
68 |
69 |
70 |
71 | org.projectlombok
72 | lombok
73 |
74 |
75 | ./target/boot
76 |
77 |
78 |
79 |
80 | repackage
81 |
82 |
83 |
84 |
85 |
86 | org.apache.maven.plugins
87 | maven-assembly-plugin
88 | 3.1.0
89 |
90 |
91 |
92 | plugin-server-cli
93 |
94 | desc_tar.xml
95 |
96 |
97 | make-tar
98 | package
99 |
100 | single
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/ArgsConstraint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | @Target(ElementType.PARAMETER)
25 | @Retention(RetentionPolicy.RUNTIME)
26 | public @interface ArgsConstraint {
27 |
28 | String name() default "";
29 |
30 | String[] constraints() default "";
31 | }
32 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/Command.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | public class Command {
23 |
24 | /**
25 | * 命令名称
26 | */
27 | private String name;
28 |
29 | /**
30 | * 命令参数描述
31 | */
32 | private List args = new ArrayList<>();
33 |
34 | /**
35 | * 使用命令名称构造命令
36 | *
37 | * @param name
38 | */
39 | public Command(String name) {
40 | this.name = name;
41 | }
42 |
43 | /**
44 | * 添加参数
45 | *
46 | * @param argName 参数名称
47 | * @param constraints 参数取值约束
48 | */
49 | public void addArgs(String argName, String type, List constraints) {
50 |
51 | Arg item = new Arg();
52 | item.name = argName;
53 | item.type = type;
54 | item.constraints = constraints;
55 |
56 | this.args.add(item);
57 | }
58 |
59 | /**
60 | * Getter method for property name. .
61 | *
62 | * @return property value of name.
63 | */
64 | public String getName() {
65 | return name;
66 | }
67 |
68 | /**
69 | * Getter method for property args. .
70 | *
71 | * @return property value of args.
72 | */
73 | public List getArgs() {
74 | return args;
75 | }
76 |
77 | /**
78 | * 参数描述类
79 | */
80 | public static class Arg {
81 | private String name;
82 | private String type;
83 | private List constraints;
84 |
85 | /**
86 | * Getter method for property name. .
87 | *
88 | * @return property value of name.
89 | */
90 | public String getName() {
91 | return name;
92 | }
93 |
94 | /**
95 | * Getter method for property constraints. .
96 | *
97 | * @return property value of constraints.
98 | */
99 | public List getConstraints() {
100 | return constraints;
101 | }
102 |
103 | /**
104 | * Getter method for property type. .
105 | *
106 | * @return property value of type.
107 | */
108 | public String getType() {
109 | return type;
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/CommandHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | @FunctionalInterface
20 | public interface CommandHandler {
21 |
22 | /**
23 | * 执行命令
24 | *
25 | * @param namespace 命令空间
26 | * @param command 命令
27 | * @param params 执行参数
28 | * @return
29 | */
30 | Object execute(String namespace, String command, String... params);
31 | }
32 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/CommandNamespace.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.util.Map;
20 |
21 | /**
22 | * 命令命名空间
23 | */
24 | public interface CommandNamespace {
25 |
26 | /**
27 | * 命名空间名称
28 | *
29 | * @return
30 | */
31 | public String name();
32 |
33 | /**
34 | * 获取命令命名空间下所有命令
35 | *
36 | * @return
37 | */
38 | public Map getCommands();
39 | }
40 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/CommandNamespaceImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 | public class CommandNamespaceImpl implements CommandNamespace {
23 | /**
24 | * 命令集合
25 | */
26 | private final Map commands = new HashMap<>();
27 |
28 | /**
29 | * 命名空间名称
30 | *
31 | * @return
32 | */
33 | @Override
34 | public String name() {
35 | return null;
36 | }
37 |
38 | /**
39 | * 往命名空间添加一个命令
40 | *
41 | * @param cmd
42 | */
43 | public void addCommand(Command cmd) {
44 | commands.put(cmd.getName(), cmd);
45 | }
46 |
47 | /**
48 | * 获取命名空间下所有命令
49 | *
50 | * @return
51 | */
52 | public Map getCommands() {
53 | return commands;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/ManagementCommandNamespace.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import com.alipay.antchain.bridge.pluginserver.cli.shell.GroovyScriptCommandNamespace;
20 |
21 | public class ManagementCommandNamespace extends GroovyScriptCommandNamespace {
22 | @Override
23 | public String name() {
24 | return "manage";
25 | }
26 |
27 | Object loadPlugins() {
28 | return queryAPI("loadPlugins");
29 | }
30 |
31 | Object startPlugins() {
32 | return queryAPI("startPlugins");
33 | }
34 |
35 | Object loadPlugin(
36 | @ArgsConstraint(name = "path") String path
37 | ) {
38 | return queryAPI("loadPlugin", path);
39 | }
40 |
41 | Object startPlugin(
42 | @ArgsConstraint(name = "path") String path
43 | ) {
44 | return queryAPI("startPlugin", path);
45 | }
46 |
47 | Object stopPlugin(
48 | @ArgsConstraint(name = "product") String product
49 | ) {
50 | return queryAPI("stopPlugin", product);
51 | }
52 |
53 | Object startPluginFromStop(
54 | @ArgsConstraint(name = "product") String product
55 | ) {
56 | return queryAPI("startPluginFromStop", product);
57 | }
58 |
59 | Object reloadPlugin(
60 | @ArgsConstraint(name = "product") String product
61 | ) {
62 | return queryAPI("reloadPlugin", product);
63 | }
64 |
65 | Object reloadPluginInNewPath(
66 | @ArgsConstraint(name = "product") String product,
67 | @ArgsConstraint(name = "path") String path
68 | ) {
69 | return queryAPI("reloadPluginInNewPath", product, path);
70 | }
71 |
72 | Object hasPlugins(
73 | @ArgsConstraint(name = "products...") String... products
74 | ) {
75 | return queryAPI("hasPlugins", products);
76 | }
77 |
78 | Object allPlugins() {
79 | return queryAPI("allPlugins");
80 | }
81 |
82 | Object hasDomains(
83 | @ArgsConstraint(name = "domains...") String... domains
84 | ) {
85 | return queryAPI("hasDomains", domains);
86 | }
87 |
88 | Object allDomains() {
89 | return queryAPI("allDomains");
90 | }
91 |
92 | Object restartBBC(
93 | @ArgsConstraint(name = "product") String product,
94 | @ArgsConstraint(name = "domain") String domain
95 | ) {
96 | return queryAPI("restartBBC", product, domain);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/NamespaceManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.util.List;
20 |
21 | public interface NamespaceManager {
22 |
23 | /**
24 | * 添加namespace
25 | *
26 | * @param commandNamespace
27 | */
28 | void addNamespace(CommandNamespace commandNamespace);
29 |
30 | /**
31 | * 获取所有namespace
32 | *
33 | * @return
34 | */
35 | List getCommandNamespaces();
36 |
37 | /**
38 | * namespace快照
39 | *
40 | * @return
41 | */
42 | String dump();
43 | }
44 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/command/NamespaceManagerImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.command;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | public class NamespaceManagerImpl implements NamespaceManager {
23 |
24 | private final List commandNamespaces = new ArrayList<>();
25 |
26 | public NamespaceManagerImpl() {
27 | addNamespace(new ManagementCommandNamespace());
28 | }
29 |
30 | @Override
31 | public void addNamespace(CommandNamespace commandNamespace) {
32 | this.commandNamespaces.add(commandNamespace);
33 | }
34 |
35 | @Override
36 | public List getCommandNamespaces() {
37 | return commandNamespaces;
38 | }
39 |
40 | @Override
41 | public String dump() {
42 | StringBuilder builder = new StringBuilder();
43 | commandNamespaces.forEach(
44 | commandNamespace -> {
45 | builder.append("\n").append(commandNamespace.name());
46 | commandNamespace.getCommands().forEach(
47 | (cmdName, cmd) -> {
48 | builder.append("\n\t.").append(cmdName);
49 | if (!cmd.getArgs().isEmpty()) {
50 | builder.append("(");
51 | cmd.getArgs().forEach(
52 | arg -> {
53 | builder.append(arg.getName()).append(",");
54 | }
55 | );
56 | builder.deleteCharAt(builder.length() - 1);
57 | builder.append(")");
58 | } else {
59 | builder.append("()");
60 | }
61 | }
62 | );
63 | }
64 | );
65 |
66 | return builder.append("\n\n").toString();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/core/ManagementGrpcClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.core;
18 |
19 | import java.io.IOException;
20 | import java.net.Socket;
21 | import java.util.List;
22 | import java.util.concurrent.TimeUnit;
23 |
24 | import cn.hutool.core.collection.CollUtil;
25 | import com.alibaba.fastjson.JSON;
26 | import com.alipay.antchain.bridge.pluginserver.managementservice.*;
27 | import io.grpc.ManagedChannel;
28 | import io.grpc.ManagedChannelBuilder;
29 |
30 | public class ManagementGrpcClient {
31 |
32 | private final ManagedChannel channel;
33 | private ManagementServiceGrpc.ManagementServiceBlockingStub blockingStub;
34 |
35 | private final String host;
36 |
37 | private final int port;
38 |
39 | public ManagementGrpcClient(int port) {
40 | this("127.0.0.1", port);
41 | }
42 |
43 | public ManagementGrpcClient(String host, int port) {
44 | this.port = port;
45 | this.host = host;
46 | this.channel = ManagedChannelBuilder.forAddress(this.host, this.port)
47 | .usePlaintext()
48 | .build();
49 | this.blockingStub = ManagementServiceGrpc.newBlockingStub(channel);
50 | }
51 |
52 | public boolean checkServerStatus() {
53 | try {
54 | Socket socket = new Socket(host, port);
55 | socket.close();
56 | return true;
57 | } catch (IOException e) {
58 | return false;
59 | }
60 | }
61 |
62 | public void shutdown() throws InterruptedException {
63 | channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
64 | }
65 |
66 | public String managePlugin(PluginManageRequest.Type type, String product, String path) {
67 | ManageResponse response = this.blockingStub.managePlugin(
68 | PluginManageRequest.newBuilder()
69 | .setType(type)
70 | .setPath(path)
71 | .setProduct(product)
72 | .build()
73 | );
74 | return response.getCode() == 0 ? "success" : "failed with msg: " + response.getErrorMsg();
75 | }
76 |
77 | public String hasPlugins(List productList) {
78 | ManageResponse response = this.blockingStub.hasPlugins(
79 | HasPluginsRequest.newBuilder()
80 | .addAllProducts(productList)
81 | .build()
82 | );
83 | if (response.getCode() != 0) {
84 | return "failed with msg: " + response.getErrorMsg();
85 | }
86 |
87 | return JSON.toJSONString(response.getHasPluginsResp().getResultsMap());
88 | }
89 |
90 | public String getAllPlugins() {
91 | ManageResponse response = this.blockingStub.allPlugins(AllPluginsRequest.newBuilder().build());
92 | if (response.getCode() != 0) {
93 | return "failed with msg: " + response.getErrorMsg();
94 | }
95 |
96 | return CollUtil.join(response.getAllPluginsResp().getProductsList(), ", ");
97 | }
98 |
99 | public String hasDomains(List domains) {
100 | ManageResponse response = this.blockingStub.hasDomains(
101 | HasDomainsRequest.newBuilder()
102 | .addAllDomains(domains)
103 | .build()
104 | );
105 | if (response.getCode() != 0) {
106 | return "failed with msg: " + response.getErrorMsg();
107 | }
108 |
109 | return JSON.toJSONString(response.getHasDomainsResp().getResultsMap());
110 | }
111 |
112 | public String getAllDomains() {
113 | ManageResponse response = this.blockingStub.allDomains(AllDomainsRequest.newBuilder().build());
114 | if (response.getCode() != 0) {
115 | return "failed with msg: " + response.getErrorMsg();
116 | }
117 |
118 | return CollUtil.join(response.getAllDomainsResp().getDomainsList(), ", ");
119 | }
120 |
121 | public String restartBBC(String product, String domain) {
122 | ManageResponse response = this.blockingStub.restartBBC(
123 | RestartBBCRequest.newBuilder()
124 | .setProduct(product)
125 | .setDomain(domain)
126 | .build()
127 | );
128 | if (response.getCode() != 0) {
129 | return "failed with msg: " + response.getErrorMsg();
130 | }
131 | return "success";
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/GroovyScriptCommandNamespace.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | import java.lang.reflect.Method;
20 | import java.lang.reflect.Parameter;
21 | import java.util.List;
22 | import java.util.stream.Stream;
23 |
24 | import cn.hutool.core.collection.ListUtil;
25 | import com.alipay.antchain.bridge.pluginserver.cli.command.ArgsConstraint;
26 | import com.alipay.antchain.bridge.pluginserver.cli.command.Command;
27 | import com.alipay.antchain.bridge.pluginserver.cli.command.CommandNamespaceImpl;
28 | import com.alipay.antchain.bridge.pluginserver.managementservice.PluginManageRequest;
29 | import com.google.common.collect.Lists;
30 |
31 | public abstract class GroovyScriptCommandNamespace extends CommandNamespaceImpl {
32 |
33 | private static final String COMMAND_NAMESPACE_NAME = "name";
34 |
35 | /**
36 | * 命名空间名称由子类实现
37 | *
38 | * @return
39 | */
40 | @Override
41 | public abstract String name();
42 |
43 | public GroovyScriptCommandNamespace() {
44 | super();
45 | loadCommand();
46 | }
47 |
48 | /**
49 | * 初始化:加载command,默认将子类所有方法解析为命令
50 | */
51 | public void loadCommand() {
52 |
53 | Method[] methods = this.getClass().getDeclaredMethods();
54 |
55 | Stream.of(methods).forEach(method -> {
56 |
57 | if (COMMAND_NAMESPACE_NAME.equals(method.getName())) {
58 | return;
59 | }
60 |
61 | Command cmd = new Command(method.getName());
62 |
63 | Parameter[] params = method.getParameters();
64 |
65 | for (Parameter param : params) {
66 |
67 | String argName = param.getName();
68 | List constraints = Lists.newArrayList();
69 |
70 | ArgsConstraint argsConstraint = param.getAnnotation(ArgsConstraint.class);
71 |
72 | if (null != argsConstraint) {
73 | if (null != argsConstraint.name() && !"".equals(argsConstraint.name().trim())) {
74 | argName = argsConstraint.name().trim();
75 | }
76 | if (null != argsConstraint.constraints()) {
77 | Stream.of(argsConstraint.constraints()).filter(
78 | constraint -> null != constraint && !"".equals(constraint.trim())).forEach(
79 | constraint -> constraints.add(constraint));
80 | }
81 | }
82 |
83 | cmd.addArgs(argName, param.getType().getSimpleName(), constraints);
84 | }
85 | addCommand(cmd);
86 | });
87 | }
88 |
89 | protected String queryAPI(String command, Object... args) {
90 |
91 | if (args != null) {
92 | String[] strArgs = new String[args.length];
93 | for (int i = 0; i < args.length; ++i) {
94 | strArgs[i] = args[i].toString();
95 | }
96 |
97 | return queryAPI(command, strArgs);
98 | } else {
99 |
100 | return queryAPI(command);
101 | }
102 | }
103 |
104 | /**
105 | * 查询api,供子类命令执行使用
106 | *
107 | * @param command
108 | * @param args
109 | * @return
110 | */
111 | protected String queryAPI(String command, String... args) {
112 |
113 | switch (command) {
114 | case "loadPlugins":
115 | return Shell.RUNTIME.getGrpcClient().managePlugin(
116 | PluginManageRequest.Type.LOAD_PLUGINS,
117 | "", ""
118 | );
119 | case "startPlugins":
120 | return Shell.RUNTIME.getGrpcClient().managePlugin(
121 | PluginManageRequest.Type.START_PLUGINS,
122 | "", ""
123 | );
124 | case "reloadPlugin":
125 | if (args.length != 1) {
126 | return "wrong length of arguments";
127 | }
128 | return Shell.RUNTIME.getGrpcClient().managePlugin(
129 | PluginManageRequest.Type.RELOAD_PLUGIN,
130 | args[0], ""
131 | );
132 | case "reloadPluginInNewPath":
133 | if (args.length != 2) {
134 | return "wrong length of arguments";
135 | }
136 | return Shell.RUNTIME.getGrpcClient().managePlugin(
137 | PluginManageRequest.Type.RELOAD_PLUGIN_IN_NEW_PATH,
138 | args[0], args[1]
139 | );
140 | case "startPlugin":
141 | if (args.length != 1) {
142 | return "wrong length of arguments";
143 | }
144 | return Shell.RUNTIME.getGrpcClient().managePlugin(
145 | PluginManageRequest.Type.START_PLUGIN,
146 | "", args[0]
147 | );
148 | case "stopPlugin":
149 | if (args.length != 1) {
150 | return "wrong length of arguments";
151 | }
152 | return Shell.RUNTIME.getGrpcClient().managePlugin(
153 | PluginManageRequest.Type.STOP_PLUGIN,
154 | args[0], ""
155 | );
156 | case "loadPlugin":
157 | if (args.length != 1) {
158 | return "wrong length of arguments";
159 | }
160 | return Shell.RUNTIME.getGrpcClient().managePlugin(
161 | PluginManageRequest.Type.LOAD_PLUGIN,
162 | "", args[0]
163 | );
164 | case "startPluginFromStop":
165 | if (args.length != 1) {
166 | return "wrong length of arguments";
167 | }
168 | return Shell.RUNTIME.getGrpcClient().managePlugin(
169 | PluginManageRequest.Type.START_PLUGIN_FROM_STOP,
170 | args[0], ""
171 | );
172 | case "hasPlugins":
173 | if (args.length == 0) {
174 | return "zero arguments";
175 | }
176 | return Shell.RUNTIME.getGrpcClient().hasPlugins(ListUtil.toList(args));
177 | case "allPlugins":
178 | if (args.length != 0) {
179 | return "wrong length of arguments";
180 | }
181 | return Shell.RUNTIME.getGrpcClient().getAllPlugins();
182 | case "hasDomains":
183 | if (args.length == 0) {
184 | return "zero arguments";
185 | }
186 | return Shell.RUNTIME.getGrpcClient().hasDomains(ListUtil.toList(args));
187 | case "allDomains":
188 | if (args.length != 0) {
189 | return "wrong length of arguments";
190 | }
191 | return Shell.RUNTIME.getGrpcClient().getAllDomains();
192 | case "restartBBC":
193 | if (args.length != 2) {
194 | return "wrong length of arguments";
195 | }
196 | return Shell.RUNTIME.getGrpcClient().restartBBC(args[0], args[1]);
197 | default:
198 | return "wrong command " + command;
199 | }
200 | }
201 |
202 | protected void print(String result) {
203 | Shell.RUNTIME.getPrinter().println(result);
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/GroovyShellProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | import java.beans.Introspector;
20 |
21 | import com.alipay.antchain.bridge.pluginserver.cli.command.NamespaceManager;
22 | import groovy.lang.GroovyShell;
23 | import groovy.lang.Script;
24 | import org.codehaus.groovy.reflection.ClassInfo;
25 | import org.codehaus.groovy.runtime.InvokerHelper;
26 |
27 | public class GroovyShellProvider extends GroovyShell implements ShellProvider {
28 |
29 | private NamespaceManager namespaceManager;
30 |
31 | public GroovyShellProvider(NamespaceManager namespaceManager) {
32 | this.namespaceManager = namespaceManager;
33 |
34 | // init GroovyShell
35 | this.namespaceManager.getCommandNamespaces().forEach(namespace -> {
36 |
37 | // only load GroovyScriptCommandNamespace
38 | if (namespace instanceof GroovyScriptCommandNamespace) {
39 | this.setVariable(namespace.name(), namespace);
40 | }
41 | });
42 | }
43 |
44 | private int cleanCount = 0;
45 |
46 | private static int CLEAN_PERIOD = 20;
47 |
48 | @Override
49 | public String execute(String cmd) {
50 | Script shell = this.parse(cmd);
51 | Object scriptObject = InvokerHelper.createScript(shell.getClass(), this.getContext()).run();
52 |
53 | // 周期清除缓存,防止OOM
54 | if((++cleanCount) % CLEAN_PERIOD == 0) {
55 | getClassLoader().clearCache();
56 | ClassInfo.clearModifiedExpandos();
57 | Introspector.flushCaches();
58 | }
59 |
60 | // execute by groovy script
61 | return scriptObject.toString();
62 | }
63 |
64 | @Override
65 | public void shutdown() {
66 | // nothing
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/JsonUtil.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Copyright 2023 Ant Group
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
19 |
20 | public class JsonUtil {
21 | /**
22 | * 得到格式化json数据 退格用\t 换行用\r
23 | */
24 | public static String format(String jsonStr) {
25 | int level = 0;
26 | StringBuffer jsonForMatStr = new StringBuffer();
27 | for (int i = 0; i < jsonStr.length(); i++) {
28 | char c = jsonStr.charAt(i);
29 | if (level > 0 && '\n' == jsonForMatStr.charAt(jsonForMatStr.length() - 1)) {
30 | jsonForMatStr.append(getLevelStr(level));
31 | }
32 | switch (c) {
33 | case '{':
34 | case '[':
35 | jsonForMatStr.append(c + "\n");
36 | level++;
37 | break;
38 | case ',':
39 | jsonForMatStr.append(c + "\n");
40 | break;
41 | case '}':
42 | case ']':
43 | jsonForMatStr.append("\n");
44 | level--;
45 | jsonForMatStr.append(getLevelStr(level));
46 | jsonForMatStr.append(c);
47 | break;
48 | default:
49 | jsonForMatStr.append(c);
50 | break;
51 | }
52 | }
53 |
54 | return jsonForMatStr.toString();
55 |
56 | }
57 |
58 | private static String getLevelStr(int level) {
59 | StringBuffer levelStr = new StringBuffer();
60 | for (int levelI = 0; levelI < level; levelI++) {
61 | levelStr.append("\t");
62 | }
63 | return levelStr.toString();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/Launcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | import java.io.*;
20 | import java.nio.charset.Charset;
21 |
22 | import cn.hutool.core.io.resource.ResourceUtil;
23 | import com.alipay.antchain.bridge.pluginserver.cli.command.NamespaceManager;
24 | import com.alipay.antchain.bridge.pluginserver.cli.command.NamespaceManagerImpl;
25 | import com.alipay.antchain.bridge.pluginserver.cli.core.ManagementGrpcClient;
26 | import org.apache.commons.cli.*;
27 |
28 | public class Launcher {
29 | private static final String OP_HELP = "h";
30 | private static final String OP_VERSION = "v";
31 | private static final String OP_PORT = "p";
32 | private static final String OP_CMD = "c";
33 | private static final String OP_FILE = "f";
34 |
35 | private static final String OP_HOST = "H";
36 |
37 | private static final Options options;
38 |
39 | static {
40 | options = new Options();
41 | options.addOption(OP_HELP, "help", false, "print help info");
42 | options.addOption(OP_VERSION, "version", false, "print version info");
43 | options.addOption(OP_PORT, "port", true, "management server port");
44 | options.addOption(OP_CMD, "command", true, "execute the command");
45 | options.addOption(OP_FILE, "file", true, "execute multiple commands in the file");
46 | options.addOption(OP_HOST, "host", true, "set the host");
47 | }
48 |
49 | public static void main(String[] args) throws ParseException {
50 |
51 | CommandLineParser parser = new DefaultParser();
52 | CommandLine cmd = parser.parse(options, args);
53 |
54 | if (cmd.hasOption(OP_HELP)) {
55 | HelpFormatter helpFormatter = new HelpFormatter();
56 | helpFormatter.printHelp("plugin server CLI", options);
57 | return;
58 | }
59 |
60 | if (cmd.hasOption(OP_VERSION)) {
61 | System.out.printf("cli version : %s\n", getVersion());
62 | return;
63 | }
64 |
65 | int port = 9091;
66 | if (cmd.hasOption(OP_PORT)) {
67 | port = Integer.parseInt(cmd.getOptionValue(OP_PORT));
68 | }
69 |
70 | // new namespace
71 | NamespaceManager namespaceManager = new NamespaceManagerImpl();
72 |
73 | // new shellProvider
74 | ShellProvider shellProvider = new GroovyShellProvider(namespaceManager);
75 |
76 | // new promptCompleter
77 | PromptCompleter promptCompleter = new PromptCompleter();
78 | promptCompleter.addNamespace(namespaceManager);
79 |
80 | // new grpcClient
81 | String host = "localhost";
82 | if (cmd.hasOption(OP_HOST)) {
83 | host = cmd.getOptionValue(OP_HOST);
84 | }
85 | ManagementGrpcClient grpcClient = new ManagementGrpcClient(host, port);
86 |
87 | if (!grpcClient.checkServerStatus()) {
88 | System.out.printf("start failed, can't connect to local server port: %d\n", port);
89 | return;
90 | }
91 |
92 | // new shell
93 | Shell shell = new Shell(shellProvider, promptCompleter, grpcClient, namespaceManager);
94 |
95 | if (cmd.hasOption(OP_CMD)) {
96 | String command = cmd.getOptionValue(OP_CMD);
97 |
98 | try {
99 | String result = shell.execute(command);
100 | System.out.println(result);
101 | } catch (Exception e) {
102 | System.out.printf("illegal command [ %s ], execute failed\n", command);
103 | }
104 | return;
105 | }
106 |
107 | if (cmd.hasOption(OP_FILE)) {
108 | String filePath = cmd.getOptionValue(OP_FILE);
109 |
110 | String command = "";
111 | try {
112 | BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath))));
113 |
114 | command = reader.readLine();
115 | StringBuilder resultBuilder = new StringBuilder();
116 | while (null != command) {
117 | try {
118 | String result = shell.execute(command);
119 | resultBuilder.append(result).append("\n");
120 | } catch (Exception e) {
121 | resultBuilder.append("error\n");
122 | }
123 | command = reader.readLine();
124 | }
125 |
126 | System.out.println(resultBuilder);
127 |
128 | } catch (FileNotFoundException e) {
129 | System.out.printf("error: file %s not found\n", filePath);
130 | } catch (IOException e) {
131 | System.out.println("error: io exception");
132 | e.printStackTrace();
133 | } catch (Exception e) {
134 | System.out.printf("illegal command [ %s ], execute failed\n", command);
135 | e.printStackTrace();
136 | }
137 |
138 | return;
139 | }
140 |
141 | shell.start();
142 |
143 | Runtime.getRuntime().addShutdownHook(new Thread(shell::stop));
144 | }
145 |
146 | public static String getVersion() {
147 | return ResourceUtil.readStr("VERSION", Charset.defaultCharset());
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/PromptCompleter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | import com.alipay.antchain.bridge.pluginserver.cli.command.CommandNamespace;
23 | import com.alipay.antchain.bridge.pluginserver.cli.command.NamespaceManager;
24 | import org.jline.reader.Candidate;
25 | import org.jline.reader.Completer;
26 | import org.jline.reader.LineReader;
27 | import org.jline.reader.ParsedLine;
28 |
29 | public class PromptCompleter implements Completer {
30 |
31 | private List namespaces = new ArrayList<>();
32 |
33 | private List reservedWords = new ArrayList<>();
34 |
35 | /**
36 | * 添加namespace
37 | *
38 | * @param namespaceManager
39 | */
40 | public void addNamespace(NamespaceManager namespaceManager) {
41 |
42 | namespaces.addAll(namespaceManager.getCommandNamespaces());
43 | }
44 |
45 | /**
46 | * 添加保留字
47 | *
48 | * @param reservedWord
49 | */
50 | public void addReservedWord(String reservedWord) {
51 | this.reservedWords.add(reservedWord);
52 | }
53 |
54 | @Override
55 | public void complete(LineReader lineReader, ParsedLine commandLine, List candidates) {
56 | assert commandLine != null;
57 | assert candidates != null;
58 |
59 | String buffer = commandLine.line().substring(0, commandLine.cursor());
60 |
61 | //如果未输入.符号,则补全保留字与命令
62 | if (!buffer.contains(".")) {
63 |
64 | // 补全保留字
65 | reservedWords.forEach(reservedWord -> {
66 | if (!buffer.isEmpty() && !reservedWord.startsWith(buffer)) {
67 | return;
68 | }
69 |
70 | candidates.add(new Candidate(reservedWord, reservedWord, null, null, null, null, true));
71 | });
72 |
73 | // 补全命令
74 | namespaces.forEach(namespace -> {
75 |
76 | if (!buffer.isEmpty() && !namespace.name().startsWith(buffer)) {
77 | return;
78 | }
79 |
80 | StringBuilder sb = new StringBuilder(namespace.name());
81 | namespace.getCommands().forEach((cmdName, cmd) -> {
82 |
83 | sb.append("\n\t.").append(cmdName);
84 | if (!cmd.getArgs().isEmpty()) {
85 | sb.append("(");
86 | cmd.getArgs().forEach(arg -> {
87 | sb.append("String ").append(arg.getName()).append(",");
88 | });
89 | sb.deleteCharAt(sb.length() - 1);
90 | sb.append(")");
91 |
92 | } else {
93 | sb.append("()");
94 | }
95 | });
96 |
97 | candidates.add(new Candidate(namespace.name() + ".", namespace.name(), null, null, null, null, true));
98 | });
99 | } else if (buffer.contains("(")) {// 已输入完整的命令(判断是否已输入"("符号),则补全详细的参数字段
100 |
101 | String[] buf = buffer.split("\\.");
102 |
103 | namespaces.forEach(namespace -> {
104 |
105 | if (!namespace.name().equals(buf[0])) {
106 | return;
107 | }
108 | namespace.getCommands().forEach((cmdName, cmd) -> {
109 |
110 | String command = buf[1].split("\\(")[0];
111 |
112 | if (cmdName.equals(command)) {
113 |
114 | StringBuilder sb = new StringBuilder(cmdName);
115 | if (!cmd.getArgs().isEmpty()) {
116 | sb.append("(");
117 | cmd.getArgs().forEach(arg -> {
118 | sb.append("\n ").append(arg.getType()).append(" ").append(arg.getName()).append(" ");
119 |
120 | if (!arg.getConstraints().isEmpty()) {
121 | sb.append(" //");
122 | arg.getConstraints().forEach(contraint -> {
123 | sb.append(contraint).append(",");
124 | });
125 | sb.deleteCharAt(sb.length() - 1);
126 | }
127 | });
128 | sb.append("\n)");
129 |
130 | candidates.add(
131 | new Candidate(buffer, sb.toString(), null, null, null,
132 | null, true));
133 | } else {
134 | sb.append("()");
135 | candidates.add(
136 | new Candidate(namespace.name() + "." + cmdName + "()", sb.toString(), null, null, null,
137 | null, true));
138 | }
139 | }
140 | });
141 | });
142 | } else { //已输入.符号,则补全匹配命令
143 | String[] buf = buffer.split("\\.");
144 |
145 | namespaces.forEach(namespace -> {
146 |
147 | if (!namespace.name().equals(buf[0])) {
148 | return;
149 | }
150 |
151 | long matchCount = namespace.getCommands().keySet().stream().filter(
152 | cmdName -> cmdName.startsWith(buf.length <= 1 ? "" : buf[1])).count();
153 |
154 | namespace.getCommands().forEach((cmdName, cmd) -> {
155 |
156 | if (cmdName.startsWith(buf.length <= 1 ? "" : buf[1])) {
157 |
158 | StringBuilder sb = new StringBuilder(cmdName);
159 | if (cmd.getArgs().isEmpty()) {
160 | sb.append("()");
161 | candidates.add(
162 | new Candidate(namespace.name() + "." + cmdName + "()", sb.toString(), null, null, null,
163 | null, true));
164 |
165 | } else if (matchCount == 1) {
166 | sb.append("(");
167 | cmd.getArgs().forEach(arg -> {
168 | sb.append("\n ").append(arg.getType()).append(" ").append(arg.getName()).append(" ");
169 |
170 | if (!arg.getConstraints().isEmpty()) {
171 | sb.append(" //");
172 | arg.getConstraints().forEach(contraint -> {
173 | sb.append(contraint).append(",");
174 | });
175 | sb.deleteCharAt(sb.length() - 1);
176 | }
177 | });
178 | sb.append("\n)");
179 |
180 | candidates.add(
181 | new Candidate(namespace.name() + "." + cmdName + "(", sb.toString(), null, null, null,
182 | null, true));
183 | } else {
184 | sb.append("(");
185 | cmd.getArgs().forEach(arg -> {
186 | sb.append(arg.getType() + " " + arg.getName()).append(",");
187 | });
188 | sb.deleteCharAt(sb.length() - 1);
189 | sb.append(")");
190 |
191 | candidates.add(
192 | new Candidate(namespace.name() + "." + cmdName + "(", sb.toString(), null, null, null,
193 | null, true));
194 | }
195 | }
196 | });
197 | });
198 | }
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/ReservedWord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | @FunctionalInterface
20 | public interface ReservedWord {
21 |
22 | void execute();
23 | }
24 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/Shell.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | import java.io.IOException;
20 | import java.io.PrintWriter;
21 | import java.nio.file.Paths;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 | import java.util.concurrent.atomic.AtomicBoolean;
25 | import java.util.concurrent.locks.ReentrantLock;
26 |
27 | import com.alipay.antchain.bridge.pluginserver.cli.command.NamespaceManager;
28 | import com.alipay.antchain.bridge.pluginserver.cli.core.ManagementGrpcClient;
29 | import org.jline.reader.LineReader;
30 | import org.jline.reader.LineReader.Option;
31 | import org.jline.reader.impl.history.DefaultHistory;
32 | import org.jline.terminal.Terminal;
33 | import org.jline.terminal.TerminalBuilder;
34 |
35 | public class Shell {
36 |
37 | private static final String PROMPT = "\033[0;37mps> \033[0m";
38 |
39 | private final NamespaceManager namespaceManager;
40 |
41 | private Terminal terminal;
42 |
43 | private GlLineReader reader;
44 |
45 | private final Map reservedWord = new HashMap<>();
46 |
47 | private AtomicBoolean loopRunning = new AtomicBoolean(false);
48 |
49 | private final ReentrantLock shellLock = new ReentrantLock();
50 |
51 | private final PromptCompleter completer;
52 |
53 | private final ShellProvider shellProvider;
54 |
55 | public final static Runtime RUNTIME = new Runtime();
56 |
57 | public Shell(ShellProvider shellProvider, PromptCompleter completer, ManagementGrpcClient grpcClient,
58 | NamespaceManager namespaceManager) {
59 |
60 | // 不可扩展参数初始化
61 | init();
62 |
63 | // 扩展初始化
64 | this.shellProvider = shellProvider;
65 | this.namespaceManager = namespaceManager;
66 |
67 | this.completer = completer;
68 | this.reservedWord.keySet().forEach(reservedWord -> this.completer.addReservedWord(reservedWord));
69 |
70 | reader.setCompleter(completer);
71 |
72 | // 运行时设置
73 | RUNTIME.setGrpcClient(grpcClient);
74 | }
75 |
76 | void init() {
77 | // init term
78 | try {
79 | terminal = TerminalBuilder.builder()
80 | .system(true)
81 | .build();
82 | } catch (IOException e) {
83 | throw new RuntimeException("can't open system stream");
84 | }
85 |
86 | // set printer
87 | RUNTIME.setPrinter(terminal.writer());
88 |
89 | // init linereader
90 | reader = new GlLineReader(terminal, "mychain-gl", new HashMap<>());
91 |
92 | reader.setVariable(LineReader.HISTORY_FILE, Paths.get("./clihistory.tmp"));
93 | reader.setHistory(new DefaultHistory(reader));
94 |
95 | reader.unsetOpt(Option.MENU_COMPLETE);
96 | reader.setOpt(Option.AUTO_LIST);
97 | reader.unsetOpt(Option.AUTO_MENU);
98 |
99 |
100 | // init shell commands
101 | initReservedWord();
102 | }
103 |
104 | public void start() {
105 |
106 | try {
107 | if (shellLock.tryLock()) {
108 |
109 | if (loopRunning.get()) {
110 | return;
111 | }
112 |
113 | loopRunning.set(true);
114 |
115 | welcome();
116 |
117 | new Thread(() -> {
118 | // start loop
119 | while (loopRunning.get()) {
120 | String cmd = reader.readLine(PROMPT);
121 |
122 | if (null == cmd || cmd.isEmpty()) {
123 | continue;
124 | }
125 |
126 | try {
127 | if (reservedWord.containsKey(cmd.trim())) {
128 |
129 | reservedWord.get(cmd.trim()).execute();
130 | continue;
131 | }
132 |
133 | String result = this.shellProvider.execute(cmd);
134 | if (null != result) {
135 | if (result.startsWith("{") || result.startsWith("[")) {
136 | RUNTIME.getPrinter().println(JsonUtil.format(result));
137 | } else {
138 | RUNTIME.getPrinter().println(result);
139 | }
140 |
141 | }
142 | } catch (Exception e) {
143 | RUNTIME.getPrinter().println("shell evaluate fail:" + e.getMessage());
144 | }
145 | }
146 | }, "shell_thread").start();
147 |
148 | }
149 | } finally {
150 | shellLock.unlock();
151 | }
152 | }
153 |
154 | public String execute(String cmd) {
155 | return this.shellProvider.execute(cmd);
156 | }
157 |
158 | public void stop() {
159 |
160 | loopRunning.set(false);
161 | try {
162 | if (null != RUNTIME.getGrpcClient()) {
163 | RUNTIME.getGrpcClient().shutdown();
164 | }
165 | } catch (InterruptedException e) {
166 | // not process
167 | }
168 | }
169 |
170 | protected void initReservedWord() {
171 | this.reservedWord.put("exit", this::exit);
172 | this.reservedWord.put("help", this::help);
173 | }
174 |
175 | protected void exit() {
176 | stop();
177 | }
178 |
179 | protected void help() {
180 | RUNTIME.getPrinter().print(namespaceManager.dump());
181 | }
182 |
183 | protected void welcome() {
184 | RUNTIME.printer.println(
185 | " ___ __ ______ __ _ ____ _ __\n" +
186 | " / | ____ / /_ / ____// /_ ____ _ (_)____ / __ ) _____ (_)____/ /____ _ ___\n" +
187 | " / /| | / __ \\ / __// / / __ \\ / __ `// // __ \\ / __ |/ ___// // __ // __ `// _ \\\n" +
188 | " / ___ | / / / // /_ / /___ / / / // /_/ // // / / / / /_/ // / / // /_/ // /_/ // __/\n" +
189 | "/_/ |_|/_/ /_/ \\__/ \\____//_/ /_/ \\__,_//_//_/ /_/ /_____//_/ /_/ \\__,_/ \\__, / \\___/\n" +
190 | " /____/ \n" +
191 | " PLUGIN SERVER CLI " + Launcher.getVersion()
192 | );
193 | RUNTIME.printer.println("\n>>> type help to see all commands...");
194 | }
195 |
196 | public static class Runtime {
197 |
198 | private PrintWriter printer;
199 |
200 | private ManagementGrpcClient grpcClient;
201 |
202 | void setPrinter(PrintWriter printer) {
203 |
204 | this.printer = printer;
205 | }
206 |
207 | void setGrpcClient(ManagementGrpcClient grpcClient) {
208 | this.grpcClient = grpcClient;
209 | }
210 |
211 | public PrintWriter getPrinter() {
212 | return printer;
213 | }
214 |
215 | public ManagementGrpcClient getGrpcClient() {
216 | return grpcClient;
217 | }
218 |
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/ps-cli/src/main/java/com/alipay/antchain/bridge/pluginserver/cli/shell/ShellProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.cli.shell;
18 |
19 | public interface ShellProvider {
20 |
21 | /**
22 | * 执行命令
23 | *
24 | * @param cmd
25 | */
26 | String execute(String cmd);
27 |
28 | /**
29 | * shutdown
30 | */
31 | void shutdown();
32 | }
33 |
--------------------------------------------------------------------------------
/ps-cli/src/main/resources/VERSION:
--------------------------------------------------------------------------------
1 | @project.version@
--------------------------------------------------------------------------------
/ps-cli/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %msg%n
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/ps-cli/src/main/resources/scripts/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | bin=`dirname "${BASH_SOURCE-$0}"`
4 | CLI_HOME=`cd "$bin"; pwd`
5 |
6 | which java > /dev/null
7 | if [ $? -eq 1 ]; then
8 | echo "no java installed. "
9 | exit 1
10 | fi
11 |
12 | Help=$(cat <<-"HELP"
13 |
14 | start.sh — Start the CLI tool to manage your plugin server
15 |
16 | Usage:
17 | start.sh
18 |
19 | Examples:
20 | 1. print help info:
21 | start.sh -h
22 | 2. identify the port number to start CLI
23 | start.sh -p 9091
24 | 3. identify the server IP to start CLI
25 | start.sh -H 0.0.0.0
26 |
27 | Options:
28 | -h print help info
29 | -p identify the port number to start CLI, default 9091
30 | -H identify the server IP to start CLI, default 127.0.0.1
31 |
32 | HELP
33 | )
34 |
35 | while getopts "hH:p:" opt
36 | do
37 | case "$opt" in
38 | "h")
39 | echo "$Help"
40 | exit 0
41 | ;;
42 | "H")
43 | HOST_IP="${OPTARG}"
44 | ;;
45 | "p")
46 | PORT=${OPTARG}
47 | ;;
48 | "?")
49 | echo "invalid arguments. "
50 | exit 1
51 | ;;
52 | *)
53 | echo "Unknown error while processing options"
54 | exit 1
55 | ;;
56 | esac
57 | done
58 |
59 | JAR_FILE=`ls ${CLI_HOME}/../lib`
60 |
61 | java -jar ${CLI_HOME}/../lib/${JAR_FILE} -p ${PORT:-9091} -H ${HOST_IP:-127.0.0.1}
--------------------------------------------------------------------------------
/ps-pluginmanager/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
--------------------------------------------------------------------------------
/ps-pluginmanager/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.alipay.antchain.bridge
8 | antchain-bridge-pluginserver
9 | 0.2.3
10 |
11 |
12 | ps-pluginmanager
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | com.alipay.antchain.bridge
23 | antchain-bridge-plugin-manager
24 |
25 |
26 | com.alipay.antchain.bridge
27 | antchain-bridge-spi
28 |
29 |
30 | com.alipay.antchain.bridge
31 | antchain-bridge-commons
32 |
33 |
34 | cn.bitfactory
35 | bid-sdk
36 |
37 |
38 | cn.bitfactory
39 | bif-chain-sdk
40 |
41 |
42 |
43 |
44 | com.alipay.antchain.bridge
45 | ps-service
46 |
47 |
48 | com.alipay.antchain.bridge
49 | ps-service
50 |
51 |
52 | com.alipay.antchain.bridge
53 | ps-service
54 |
55 |
56 | com.alipay.antchain.bridge
57 | ps-service
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/ps-pluginmanager/src/main/java/com/alipay/antchain/bridge/pluginserver/pluginmanager/IPluginManagerWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.pluginmanager;
18 |
19 | import com.alipay.antchain.bridge.plugins.manager.core.IAntChainBridgePlugin;
20 | import com.alipay.antchain.bridge.plugins.spi.bbc.IBBCService;
21 |
22 | import java.util.List;
23 |
24 | public interface IPluginManagerWrapper {
25 | void loadPlugins();
26 |
27 | void startPlugins();
28 |
29 | void loadPlugin(String path);
30 |
31 | void startPlugin(String path);
32 |
33 | void stopPlugin(String product);
34 |
35 | void startPluginFromStop(String product);
36 |
37 | void reloadPlugin(String product);
38 |
39 | void reloadPlugin(String product, String path);
40 |
41 | IAntChainBridgePlugin getPlugin(String product);
42 |
43 | boolean hasPlugin(String product);
44 |
45 | List allSupportProducts();
46 |
47 | IBBCService createBBCService(String product, String domain);
48 |
49 | IBBCService getBBCService(String product, String domain);
50 |
51 | boolean hasDomain(String domain);
52 |
53 | List allRunningDomains();
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/ps-pluginmanager/src/main/java/com/alipay/antchain/bridge/pluginserver/pluginmanager/PluginManagerWrapperImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.pluginmanager;
18 |
19 | import java.nio.charset.StandardCharsets;
20 | import java.nio.file.Path;
21 | import java.nio.file.Paths;
22 | import java.util.*;
23 | import java.util.stream.Collectors;
24 |
25 | import ch.qos.logback.classic.AsyncAppender;
26 | import ch.qos.logback.classic.Level;
27 | import ch.qos.logback.classic.LoggerContext;
28 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
29 | import ch.qos.logback.classic.spi.ILoggingEvent;
30 | import ch.qos.logback.core.rolling.RollingFileAppender;
31 | import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
32 | import ch.qos.logback.core.util.FileSize;
33 | import cn.hutool.core.collection.ListUtil;
34 | import cn.hutool.core.util.ObjectUtil;
35 | import cn.hutool.core.util.StrUtil;
36 | import com.alipay.antchain.bridge.commons.core.base.CrossChainDomain;
37 | import com.alipay.antchain.bridge.plugins.manager.AntChainBridgePluginManagerFactory;
38 | import com.alipay.antchain.bridge.plugins.manager.core.IAntChainBridgePlugin;
39 | import com.alipay.antchain.bridge.plugins.manager.core.IAntChainBridgePluginManager;
40 | import com.alipay.antchain.bridge.plugins.spi.bbc.IBBCService;
41 | import lombok.extern.slf4j.Slf4j;
42 | import org.pf4j.ClassLoadingStrategy;
43 | import org.slf4j.Logger;
44 | import org.slf4j.LoggerFactory;
45 | import org.springframework.beans.factory.annotation.Autowired;
46 | import org.springframework.beans.factory.annotation.Value;
47 | import org.springframework.stereotype.Component;
48 |
49 | @Slf4j
50 | @Component
51 | public class PluginManagerWrapperImpl implements IPluginManagerWrapper {
52 |
53 | private final IAntChainBridgePluginManager manager;
54 |
55 | private final String bbcLoggerDir;
56 |
57 | @Value("${pluginserver.plugin.log.bbc.max_history:3}")
58 | private int maxBBCLogHistory;
59 |
60 | @Value("${pluginserver.plugin.log.bbc.max_file_size:30mb}")
61 | private String maxBBCLogFileSize;
62 |
63 | @Value("${pluginserver.plugin.log.bbc.level:info}")
64 | private String bbcLogLevel;
65 |
66 | @Value("${pluginserver.plugin.log.bbc.on:true}")
67 | private boolean isBBCLogOn;
68 |
69 | private final Map bbcLoggerMap = new HashMap<>();
70 |
71 | @Autowired
72 | public PluginManagerWrapperImpl(
73 | @Value("${pluginserver.plugin.repo}") String path,
74 | @Value("${logging.file.path}") String appLogDir,
75 | @Value("${pluginserver.plugin.policy.classloader.resource.ban-with-prefix.APPLICATION:}") String[] resourceBannedPrefixOnAppLevel
76 | ) {
77 | log.info("plugins path: {}", Paths.get(path).toAbsolutePath());
78 |
79 | this.bbcLoggerDir = Paths.get(appLogDir, "bbc").toAbsolutePath().toString();
80 | log.info("bbc logger base dir: {}", Paths.get(bbcLoggerDir).toAbsolutePath());
81 |
82 | this.manager = AntChainBridgePluginManagerFactory.createPluginManager(
83 | path,
84 | ObjectUtil.defaultIfNull(convertPathPrefixBannedMap(resourceBannedPrefixOnAppLevel), new HashMap<>())
85 | );
86 | loadPlugins();
87 | startPlugins();
88 | }
89 |
90 | private Map> convertPathPrefixBannedMap(
91 | String[] resourceBannedPrefixOnAppLevel
92 | ) {
93 | Map> result = new HashMap<>();
94 |
95 | Set appSet = new HashSet<>(ListUtil.of(resourceBannedPrefixOnAppLevel));
96 | result.put(ClassLoadingStrategy.Source.APPLICATION, appSet);
97 |
98 | return result;
99 | }
100 |
101 | @Override
102 | public void loadPlugins() {
103 | manager.loadPlugins();
104 | }
105 |
106 | @Override
107 | public void startPlugins() {
108 | manager.startPlugins();
109 | }
110 |
111 | @Override
112 | public void loadPlugin(String path) {
113 | manager.loadPlugin(Paths.get(path));
114 | }
115 |
116 | @Override
117 | public void startPlugin(String path) {
118 | manager.startPlugin(Paths.get(path));
119 | }
120 |
121 | @Override
122 | public void stopPlugin(String product) {
123 | manager.stopPlugin(product);
124 | }
125 |
126 | @Override
127 | public void startPluginFromStop(String product) {
128 | manager.startPluginFromStop(product);
129 | }
130 |
131 | @Override
132 | public void reloadPlugin(String product) {
133 | manager.reloadPlugin(product);
134 | }
135 |
136 | @Override
137 | public void reloadPlugin(String product, String path) {
138 | manager.reloadPlugin(product, Paths.get(path));
139 | }
140 |
141 | @Override
142 | public IAntChainBridgePlugin getPlugin(String product) {
143 | return manager.getPlugin(product);
144 | }
145 |
146 | @Override
147 | public boolean hasPlugin(String product) {
148 | return manager.hasPlugin(product);
149 | }
150 |
151 | @Override
152 | public List allSupportProducts() {
153 | return manager.allSupportProducts();
154 | }
155 |
156 | @Override
157 | public IBBCService createBBCService(String product, String domain) {
158 | return manager.createBBCService(product, new CrossChainDomain(domain), createBBCServiceLogger(product, domain));
159 | }
160 |
161 | @Override
162 | public IBBCService getBBCService(String product, String domain) {
163 | return manager.getBBCService(product, new CrossChainDomain(domain));
164 | }
165 |
166 | @Override
167 | public boolean hasDomain(String domain) {
168 | return manager.hasDomain(new CrossChainDomain(domain));
169 | }
170 |
171 | @Override
172 | public List allRunningDomains() {
173 | return manager.allRunningDomains().stream().map(CrossChainDomain::toString).collect(Collectors.toList());
174 | }
175 |
176 | private Logger createBBCServiceLogger(String product, String domain) {
177 | if (!isBBCLogOn) {
178 | return null;
179 | }
180 | String loggerName = getLoggerName(product, domain);
181 | if (bbcLoggerMap.containsKey(loggerName) && ObjectUtil.isNotNull(bbcLoggerMap.get(loggerName))) {
182 | return bbcLoggerMap.get(loggerName);
183 | }
184 | Path logFile = Paths.get(bbcLoggerDir, product, domain + ".log");
185 | Logger logger = LoggerFactory.getLogger(loggerName);
186 | if (logger instanceof ch.qos.logback.classic.Logger) {
187 | log.debug("using logback for bbc logger");
188 |
189 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
190 |
191 | PatternLayoutEncoder encoder = new PatternLayoutEncoder();
192 | encoder.setContext(context);
193 | encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n");
194 | encoder.setCharset(StandardCharsets.UTF_8);
195 | encoder.start();
196 |
197 | SizeAndTimeBasedRollingPolicy rollingPolicy = new SizeAndTimeBasedRollingPolicy<>();
198 | rollingPolicy.setContext(context);
199 | rollingPolicy.setFileNamePattern(logFile + ".%d{yyyy-MM-dd}.%i");
200 | rollingPolicy.setMaxHistory(maxBBCLogHistory);
201 | rollingPolicy.setMaxFileSize(FileSize.valueOf(maxBBCLogFileSize));
202 |
203 | RollingFileAppender appender = new RollingFileAppender<>();
204 | appender.setContext(context);
205 | appender.setEncoder(encoder);
206 | appender.setFile(logFile.toString());
207 | appender.setRollingPolicy(rollingPolicy);
208 |
209 | rollingPolicy.setParent(appender);
210 | rollingPolicy.start();
211 | appender.start();
212 |
213 | AsyncAppender asyncAppender = new AsyncAppender();
214 | asyncAppender.setContext(context);
215 | asyncAppender.setName(loggerName);
216 | asyncAppender.addAppender(appender);
217 | asyncAppender.start();
218 |
219 | ch.qos.logback.classic.Logger loggerLogback = (ch.qos.logback.classic.Logger) logger;
220 | loggerLogback.setLevel(Level.toLevel(bbcLogLevel));
221 | loggerLogback.setAdditive(false);
222 | loggerLogback.addAppender(asyncAppender);
223 |
224 | bbcLoggerMap.put(loggerName, loggerLogback);
225 | log.info("bbc logger {} created", loggerName);
226 |
227 | return loggerLogback;
228 | }
229 |
230 | log.debug("logger library not support for now");
231 | return null;
232 | }
233 |
234 | private String getLoggerName(String product, String domain) {
235 | return StrUtil.format("{}::{}", product, domain);
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/ps-server/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
--------------------------------------------------------------------------------
/ps-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.alipay.antchain.bridge
8 | antchain-bridge-pluginserver
9 | 0.2.3
10 |
11 |
12 | ps-server
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | net.devh
23 | grpc-server-spring-boot-starter
24 |
25 |
26 |
27 | com.alipay.antchain.bridge
28 | ps-service
29 |
30 |
31 |
32 | com.alipay.antchain.bridge
33 | ps-pluginmanager
34 |
35 |
36 |
37 | io.netty
38 | netty-tcnative-boringssl-static
39 |
40 |
41 |
42 | com.alipay.antchain.bridge
43 | antchain-bridge-plugin-manager
44 |
45 |
46 |
47 | com.alipay.antchain.bridge
48 | antchain-bridge-spi
49 |
50 |
51 |
52 | com.alipay.antchain.bridge
53 | antchain-bridge-plugin-lib
54 |
55 |
56 |
57 | org.pf4j
58 | pf4j
59 |
60 |
61 |
62 | org.projectlombok
63 | lombok
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/ps-server/src/main/java/com/alipay/antchain/bridge/pluginserver/server/PluginManagementServiceImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.server;
18 |
19 | import java.util.Comparator;
20 | import java.util.stream.Collectors;
21 | import javax.annotation.Resource;
22 |
23 | import cn.hutool.core.util.ObjectUtil;
24 | import com.alipay.antchain.bridge.plugins.spi.bbc.IBBCService;
25 | import com.alipay.antchain.bridge.pluginserver.managementservice.*;
26 | import com.alipay.antchain.bridge.pluginserver.pluginmanager.IPluginManagerWrapper;
27 | import com.alipay.antchain.bridge.pluginserver.server.exception.ServerErrorCodeEnum;
28 | import io.grpc.stub.StreamObserver;
29 | import lombok.extern.slf4j.Slf4j;
30 | import org.springframework.stereotype.Component;
31 |
32 | @Component
33 | @Slf4j
34 | public class PluginManagementServiceImpl extends ManagementServiceGrpc.ManagementServiceImplBase {
35 |
36 | @Resource
37 | private IPluginManagerWrapper pluginManagerWrapper;
38 |
39 | /**
40 | *
41 | * maintenance personnel may invoke this interface to load, unload, start, and stop plugins
42 | *
43 | */
44 | public void managePlugin(PluginManageRequest request, StreamObserver responseObserver) {
45 | String path = request.getPath();
46 | String product = request.getProduct();
47 | log.info("ManageRequest [path: {}, product: {}, request: {}]", path, product, request.getType());
48 |
49 | ManageResponse resp;
50 |
51 | switch (request.getType()){
52 | case LOAD_PLUGINS:
53 | resp = handleLoadPlugins();
54 | break;
55 | case START_PLUGINS:
56 | resp = handleStartPlugins();
57 | break;
58 | case LOAD_PLUGIN:
59 | resp = handleLoadPlugin(path);
60 | break;
61 | case START_PLUGIN:
62 | resp = handleStartPlugin(path);
63 | break;
64 | case STOP_PLUGIN:
65 | resp = handleStopPlugin(product);
66 | break;
67 | case START_PLUGIN_FROM_STOP:
68 | resp = handleStartPluginFromStop(product);
69 | break;
70 | case RELOAD_PLUGIN:
71 | resp = handleReloadPlugin(product);
72 | break;
73 | case RELOAD_PLUGIN_IN_NEW_PATH:
74 | resp = handleReloadPluginInNewPath(product, path);
75 | break;
76 | default:
77 | log.error("managePlugin fail [path: {}, product: {}, request: {}, errorCode: {}, errorMsg: {}]", path, product, request.getType(), ServerErrorCodeEnum.UNSUPPORT_MANAGE_REQUEST_ERROR.getErrorCode(), ServerErrorCodeEnum.UNSUPPORT_MANAGE_REQUEST_ERROR.getShortMsg());
78 | resp = ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.UNSUPPORT_MANAGE_REQUEST_ERROR);
79 | break;
80 | }
81 |
82 | responseObserver.onNext(resp);
83 | responseObserver.onCompleted();
84 | }
85 |
86 | private ManageResponse handleLoadPlugins() {
87 | try {
88 | pluginManagerWrapper.loadPlugins();
89 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
90 | } catch (Exception e){
91 | log.error("manage(handleLoadPlugins) fail [errorCode: {}, errorMsg: {}]", ServerErrorCodeEnum.MANAGE_LOAD_PLUGINS_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_LOAD_PLUGINS_ERROR.getShortMsg(), e);
92 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_LOAD_PLUGINS_ERROR, e.toString());
93 | }
94 | }
95 |
96 | private ManageResponse handleStartPlugins() {
97 | try {
98 | pluginManagerWrapper.startPlugins();
99 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
100 | } catch (Exception e){
101 | log.error("manage(handleStartPlugins) fail [errorCode: {}, errorMsg: {}]", ServerErrorCodeEnum.MANAGE_START_PLUGINS_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_START_PLUGINS_ERROR.getShortMsg(), e);
102 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_START_PLUGINS_ERROR, e.toString());
103 | }
104 | }
105 |
106 | private ManageResponse handleLoadPlugin(String path) {
107 | try {
108 | pluginManagerWrapper.loadPlugin(path);
109 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
110 | } catch (Exception e){
111 | log.error("manage(handleLoadPlugin) fail [path: {}, errorCode: {}, errorMsg: {}]", path, ServerErrorCodeEnum.MANAGE_LOAD_PLUGIN_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_LOAD_PLUGIN_ERROR.getShortMsg(), e);
112 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_LOAD_PLUGIN_ERROR, e.toString());
113 | }
114 | }
115 |
116 | private ManageResponse handleStartPlugin(String path) {
117 | try {
118 | pluginManagerWrapper.startPlugin(path);
119 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
120 | } catch (Exception e){
121 | log.error("manage(handleStartPlugin) fail [path: {}, errorCode: {}, errorMsg: {}]", path, ServerErrorCodeEnum.MANAGE_START_PLUGIN_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_START_PLUGIN_ERROR.getShortMsg(), e);
122 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_START_PLUGIN_ERROR, e.toString());
123 | }
124 | }
125 |
126 | private ManageResponse handleStopPlugin(String product) {
127 | try {
128 | pluginManagerWrapper.stopPlugin(product);
129 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
130 | } catch (Exception e){
131 | log.error("manage(handleStopPlugin) fail [product: {}, errorCode: {}, errorMsg: {}]", product, ServerErrorCodeEnum.MANAGE_STOP_PLUGIN_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_STOP_PLUGIN_ERROR.getShortMsg(), e);
132 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_STOP_PLUGIN_ERROR, e.toString());
133 | }
134 | }
135 |
136 | private ManageResponse handleStartPluginFromStop(String product) {
137 | try {
138 | pluginManagerWrapper.startPluginFromStop(product);
139 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
140 | } catch (Exception e){
141 | log.error("manage(handleStartPluginFromStop) fail [product: {}, errorCode: {}, errorMsg: {}]", product, ServerErrorCodeEnum.MANAGE_START_PLUGIN_FROM_STOP_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_START_PLUGIN_FROM_STOP_ERROR.getShortMsg(), e);
142 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_START_PLUGIN_FROM_STOP_ERROR, e.toString());
143 | }
144 | }
145 |
146 | private ManageResponse handleReloadPlugin(String product) {
147 | try {
148 | pluginManagerWrapper.reloadPlugin(product);
149 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
150 | } catch (Exception e){
151 | log.error("manage(handleReloadPlugin) fail [product: {}, errorCode: {}, errorMsg: {}]", product, ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_ERROR.getErrorCode(), ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_ERROR.getShortMsg(), e);
152 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_ERROR, e.toString());
153 | }
154 | }
155 |
156 | private ManageResponse handleReloadPluginInNewPath(String product, String path) {
157 | try {
158 | pluginManagerWrapper.reloadPlugin(product, path);
159 | return ResponseBuilder.buildPluginManageSuccessResp(PluginManageResp.newBuilder());
160 | } catch (Exception e){
161 | log.error("manage(handleReloadPluginInNewPath) fail [product: {}, path: {}, errorCode: {}, errorMsg: {}]", ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_IN_NEW_PATH_ERROR.getErrorCode(), product, path, ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_IN_NEW_PATH_ERROR.getShortMsg(), e);
162 | return ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_RELOAD_PLUGIN_IN_NEW_PATH_ERROR, e.toString());
163 | }
164 | }
165 |
166 | /**
167 | *
168 | * return whether the plugins of the products are supported
169 | *
170 | */
171 | @Override
172 | public void hasPlugins(HasPluginsRequest request, StreamObserver responseObserver) {
173 | responseObserver.onNext(
174 | ResponseBuilder.buildHasPluginsResp(
175 | HasPluginsResp.newBuilder()
176 | .putAllResults(
177 | request.getProductsList().stream()
178 | .distinct()
179 | .collect(Collectors.toMap(p -> p, p -> pluginManagerWrapper.hasPlugin(p)))
180 | )
181 | )
182 | );
183 | responseObserver.onCompleted();
184 | }
185 |
186 | /**
187 | *
188 | * return all supported plugin products
189 | *
190 | */
191 | @Override
192 | public void allPlugins(AllPluginsRequest request, StreamObserver responseObserver) {
193 | responseObserver.onNext(
194 | ResponseBuilder.buildAllPluginsResp(
195 | AllPluginsResp.newBuilder().addAllProducts(pluginManagerWrapper.allSupportProducts().stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList()))
196 | )
197 | );
198 | responseObserver.onCompleted();
199 | }
200 |
201 | /**
202 | *
203 | * return whether the chains of the domains are running
204 | *
205 | */
206 | @Override
207 | public void hasDomains(HasDomainsRequest request, StreamObserver responseObserver) {
208 | responseObserver.onNext(ResponseBuilder.buildHasDomainsResp(HasDomainsResp.newBuilder()
209 | .putAllResults(request.getDomainsList().stream().distinct().collect(Collectors.toMap(d -> d, d -> pluginManagerWrapper.hasDomain(d))))
210 | )
211 | );
212 | responseObserver.onCompleted();
213 | }
214 |
215 | /**
216 | *
217 | * return domains of all running chains
218 | *
219 | */
220 | @Override
221 | public void allDomains(AllDomainsRequest request, StreamObserver responseObserver) {
222 | responseObserver.onNext(
223 | ResponseBuilder.buildAllDomainsResp(
224 | AllDomainsResp.newBuilder().addAllDomains(pluginManagerWrapper.allRunningDomains().stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList()))
225 | )
226 | );
227 | responseObserver.onCompleted();
228 | }
229 |
230 | @Override
231 | public void restartBBC(RestartBBCRequest request, StreamObserver responseObserver) {
232 | if (!pluginManagerWrapper.hasPlugin(request.getProduct())) {
233 | responseObserver.onNext(
234 | ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_RESTART_BBC_ERROR, "product not found")
235 | );
236 | responseObserver.onCompleted();
237 | return;
238 | }
239 | if (!pluginManagerWrapper.hasDomain(request.getDomain())) {
240 | responseObserver.onNext(
241 | ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_RESTART_BBC_ERROR, "domain not found")
242 | );
243 | responseObserver.onCompleted();
244 | return;
245 | }
246 | try {
247 | IBBCService oldBbcService = pluginManagerWrapper.getBBCService(request.getProduct(), request.getDomain());
248 | if (ObjectUtil.isNull(oldBbcService)) {
249 | throw new RuntimeException("null BBC service for domain " + request.getDomain());
250 | }
251 | IBBCService newBbcService = pluginManagerWrapper.createBBCService(request.getProduct(), request.getDomain());
252 | newBbcService.startup(oldBbcService.getContext());
253 | } catch (Exception e) {
254 | log.error("restartBBC fail [errorCode: {}, errorMsg: {}]",
255 | ServerErrorCodeEnum.MANAGE_RESTART_BBC_ERROR.getErrorCode(),
256 | ServerErrorCodeEnum.MANAGE_RESTART_BBC_ERROR.getShortMsg(), e);
257 | responseObserver.onNext(
258 | ResponseBuilder.buildFailManageResp(ServerErrorCodeEnum.MANAGE_RESTART_BBC_ERROR, "UNKNOWN")
259 | );
260 | responseObserver.onCompleted();
261 | return;
262 | }
263 | responseObserver.onNext(
264 | ResponseBuilder.buildRestartBBCResp(RestartBBCResp.newBuilder())
265 | );
266 | responseObserver.onCompleted();
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/ps-server/src/main/java/com/alipay/antchain/bridge/pluginserver/server/ResponseBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.server;
18 |
19 | import com.alipay.antchain.bridge.pluginserver.managementservice.*;
20 | import com.alipay.antchain.bridge.pluginserver.server.exception.ServerErrorCodeEnum;
21 | import com.alipay.antchain.bridge.pluginserver.service.*;
22 | import lombok.extern.slf4j.Slf4j;
23 |
24 | @Slf4j
25 | public class ResponseBuilder {
26 |
27 | public static Response buildBBCSuccessResp(CallBBCResponse.Builder respBuilder) {
28 | log.debug("call bbc service response success");
29 |
30 | return Response.newBuilder()
31 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
32 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
33 | .setBbcResp(respBuilder).build();
34 | }
35 |
36 | public static Response buildHeartbeatSuccessResp(HeartbeatResponse.Builder respBuilder) {
37 | log.debug("HeartbeatResponse, domains: {}, product: {}", respBuilder.getDomainsList(), respBuilder.getProductsList());
38 |
39 | return Response.newBuilder()
40 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
41 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
42 | .setHeartbeatResp(respBuilder).build();
43 | }
44 |
45 | public static Response buildIfProductSupportSuccessResp(IfProductSupportResponse.Builder respBuilder) {
46 | log.debug("IfProductSupportResponse: {}", respBuilder.getResults());
47 |
48 | return Response.newBuilder()
49 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
50 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
51 | .setIfProductSupportResp(respBuilder).build();
52 | }
53 |
54 | public static Response buildIfDomainAliveSuccessResp(IfDomainAliveResponse.Builder respBuilder) {
55 | log.debug("IfDomainAliveResponse: {}", respBuilder.getResults());
56 |
57 | return Response.newBuilder()
58 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
59 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
60 | .setIfDomainAliveResp(respBuilder).build();
61 | }
62 |
63 | public static Response buildFailResp(ServerErrorCodeEnum errorCodeEnum) {
64 |
65 | return Response.newBuilder()
66 | .setCode(errorCodeEnum.getErrorCode())
67 | .setErrorMsg(errorCodeEnum.getShortMsg()).build();
68 | }
69 |
70 | public static Response buildFailResp(ServerErrorCodeEnum errorCodeEnum, String longMsg) {
71 |
72 | return Response.newBuilder()
73 | .setCode(errorCodeEnum.getErrorCode())
74 | .setErrorMsg(longMsg).build();
75 | }
76 |
77 | // ManageResponse builder ======================================
78 |
79 | public static ManageResponse buildPluginManageSuccessResp(PluginManageResp.Builder respBuilder) {
80 | log.debug("plugin manage response success");
81 |
82 | return ManageResponse.newBuilder()
83 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
84 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
85 | .setPluginManageResp(respBuilder).build();
86 | }
87 |
88 | public static ManageResponse buildHasPluginsResp(HasPluginsResp.Builder respBuilder) {
89 | log.debug("HasPluginsResponse: {}", respBuilder.getResults());
90 |
91 | return ManageResponse.newBuilder()
92 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
93 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
94 | .setHasPluginsResp(respBuilder).build();
95 | }
96 |
97 | public static ManageResponse buildAllPluginsResp(AllPluginsResp.Builder respBuilder) {
98 | log.debug("AllPluginResponse: {}", respBuilder.getProductsList());
99 |
100 | return ManageResponse.newBuilder()
101 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
102 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
103 | .setAllPluginsResp(respBuilder).build();
104 | }
105 |
106 | public static ManageResponse buildHasDomainsResp(HasDomainsResp.Builder respBuilder) {
107 | log.debug("HasDomainsResponse: {}", respBuilder.getResults());
108 |
109 | return ManageResponse.newBuilder()
110 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
111 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
112 | .setHasDomainsResp(respBuilder).build();
113 | }
114 |
115 | public static ManageResponse buildAllDomainsResp(AllDomainsResp.Builder respBuilder) {
116 | log.debug("AllDomainsResponse: {}", respBuilder.getDomainsList());
117 |
118 | return ManageResponse.newBuilder()
119 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
120 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
121 | .setAllDomainsResp(respBuilder).build();
122 | }
123 |
124 | public static ManageResponse buildRestartBBCResp(RestartBBCResp.Builder respBuilder) {
125 | log.debug("restart bbc service success");
126 | return ManageResponse.newBuilder()
127 | .setCode(ServerErrorCodeEnum.SUCCESS.getErrorCode())
128 | .setErrorMsg(ServerErrorCodeEnum.SUCCESS.getShortMsg())
129 | .setRestartBBCResp(respBuilder)
130 | .build();
131 | }
132 |
133 | public static ManageResponse buildFailManageResp(ServerErrorCodeEnum errorCodeEnum) {
134 |
135 | return ManageResponse.newBuilder()
136 | .setCode(errorCodeEnum.getErrorCode())
137 | .setErrorMsg(errorCodeEnum.getShortMsg()).build();
138 | }
139 |
140 | public static ManageResponse buildFailManageResp(ServerErrorCodeEnum errorCodeEnum, String longMsg) {
141 |
142 | return ManageResponse.newBuilder()
143 | .setCode(errorCodeEnum.getErrorCode())
144 | .setErrorMsg(longMsg).build();
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/ps-server/src/main/java/com/alipay/antchain/bridge/pluginserver/server/exception/ServerErrorCodeEnum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Ant Group
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alipay.antchain.bridge.pluginserver.server.exception;
18 |
19 | import lombok.Getter;
20 |
21 | @Getter
22 | public enum ServerErrorCodeEnum {
23 | // TODO: add element when you need
24 |
25 | SUCCESS(0, "success"),
26 |
27 | UNSUPPORT_BBC_REQUEST_ERROR(200, "unsupport bbc request type"),
28 |
29 | BBC_GET_SERVICE_ERROR(201, "[bbc] get service failed"),
30 |
31 | BBC_CREATE_ERROR(202, "[bbc] create service failed"),
32 |
33 | BBC_STARTUP_ERROR(203, "[bbc] start up failed"),
34 |
35 | BBC_SHUTDOWN_ERROR(204, "[bbc] shut down failed"),
36 |
37 | BBC_GETCONTEXT_ERROR(205, "[bbc] get context failed"),
38 |
39 | BBC_SETUPSDPMESSAGECONTRACT_ERROR(206, "[bbc] set up sdp contract failed"),
40 |
41 | BBC_SETUPAUTHMESSAGECONTRACT_ERROR(207, "[bbc] set up am contract failed"),
42 |
43 | BBC_SETPROTOCOL_ERROR(208, "[bbc] set protocol failed"),
44 |
45 | BBC_SETAMCONTRACT_ERROR(209, "[bbc] set am contract failed"),
46 |
47 | BBC_ADDVALIDRELAYER_ERROR(210, "[bbc] add valid relayer failed"),
48 |
49 | BBC_RELAYAUTHMESSAGE_ERROR(211, "[bbc] forward relayer auth msg failed"),
50 |
51 | BBC_READ_CCMSG_RET_ERROR(212, "[bbc] read cross chain msg receipt failed"),
52 |
53 | BBC_READCROSSCHAINMESSAGESBYHEIGHT_ERROR(213, "[bbc] read cross chain msg by height failed"),
54 |
55 | BBC_QUERYSDPMESSAGESEQ_ERROR(214, "[bbc] query sdp msg sequence failed"),
56 |
57 | BBC_QUERYLATESTHEIGHT_ERROR(215, "[bbc] query latest height failed"),
58 |
59 | BBC_SETLOCALDOMAIN_ERROR(216, "[bbc] set local domain failed"),
60 |
61 | BBC_OBJECT_NOT_STARTED(217, "[bbc] none bbc object started"),
62 |
63 | BBC_PLUGIN_NOT_SUPPORT(218, "[bbc] none plugin found"),
64 |
65 | UNSUPPORT_MANAGE_REQUEST_ERROR(300, "unsupport manage request type"),
66 |
67 | MANAGE_LOAD_PLUGINS_ERROR(301, "[manage] load plugins failed"),
68 |
69 | MANAGE_START_PLUGINS_ERROR(302, "[manage] start plugins failed"),
70 |
71 | MANAGE_LOAD_PLUGIN_ERROR(303, "[manage] load plugin in the specified path failed"),
72 |
73 | MANAGE_START_PLUGIN_ERROR(304, "[manage] start plugin in the specified path failed"),
74 |
75 | MANAGE_STOP_PLUGIN_ERROR(305, "[manage] stop plugin of specified product failed"),
76 |
77 | MANAGE_START_PLUGIN_FROM_STOP_ERROR(306, "[manage] start plugin of specified product from stop failed"),
78 |
79 | MANAGE_RELOAD_PLUGIN_ERROR(307, "[manage] reload plugin failed"),
80 |
81 | MANAGE_RELOAD_PLUGIN_IN_NEW_PATH_ERROR(308, "[manage] reload plugin in new path failed"),
82 |
83 | MANAGE_RESTART_BBC_ERROR(309, "[manage] restart bbc failed"),
84 |
85 | UNKNOWN_ERROR(100, "unknow error");
86 |
87 | /**
88 | * Error code for errors happened in project {@code antchain-bridge-pluginserver}
89 | */
90 | private final int errorCode;
91 |
92 | /**
93 | * Every code has a short message to describe the error stuff
94 | */
95 | private final String shortMsg;
96 |
97 | ServerErrorCodeEnum(int errorCode, String shortMsg) {
98 | this.errorCode = errorCode;
99 | this.shortMsg = shortMsg;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/ps-server/src/main/java/com/alipay/antchain/bridge/pluginserver/server/interceptor/RequestTraceInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.alipay.antchain.bridge.pluginserver.server.interceptor;
2 |
3 | import java.net.InetSocketAddress;
4 |
5 | import cn.hutool.core.util.ObjectUtil;
6 | import cn.hutool.core.util.StrUtil;
7 | import io.grpc.*;
8 | import lombok.extern.slf4j.Slf4j;
9 |
10 | @Slf4j(topic = "req-trace")
11 | public class RequestTraceInterceptor implements ServerInterceptor {
12 |
13 | @Override
14 | public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) {
15 | InetSocketAddress clientAddr = (InetSocketAddress) call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
16 | if (StrUtil.equalsIgnoreCase(call.getMethodDescriptor().getBareMethodName(), "heartbeat")) {
17 | if (ObjectUtil.isNull(clientAddr)) {
18 | log.info("heartbeat from relayer without address found");
19 | } else {
20 | log.info("heartbeat from relayer {}:{}", clientAddr.getHostString(), clientAddr.getPort());
21 | }
22 | } else if (StrUtil.equalsIgnoreCase(call.getMethodDescriptor().getBareMethodName(), "bbcCall")) {
23 | if (ObjectUtil.isNull(clientAddr)) {
24 | log.debug("bbc call from relayer without address found");
25 | } else {
26 | log.debug("bbc call from relayer {}:{}", clientAddr.getHostString(), clientAddr.getPort());
27 | }
28 | }
29 |
30 | return next.startCall(call, headers);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ps-service/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
--------------------------------------------------------------------------------
/ps-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.alipay.antchain.bridge
8 | antchain-bridge-pluginserver
9 | 0.2.3
10 |
11 |
12 | ps-service
13 |
14 |
15 |
16 | io.grpc
17 | grpc-stub
18 |
19 |
20 | io.grpc
21 | grpc-protobuf
22 |
23 |
24 |
25 | jakarta.annotation
26 | jakarta.annotation-api
27 | true
28 |
29 |
30 |
31 |
32 |
33 |
34 | kr.motd.maven
35 | os-maven-plugin
36 | 1.7.0
37 |
38 |
39 |
40 |
41 |
42 | org.xolstice.maven.plugins
43 | protobuf-maven-plugin
44 | ${protobuf-plugin.version}
45 |
46 | com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
47 | grpc-java
48 | io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
49 |
50 |
51 |
52 |
53 | compile
54 | compile-custom
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/ps-service/src/main/proto/managementserver.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package com.alipay.antchain.bridge.pluginserver.managementservice;
4 |
5 | option java_multiple_files = true;
6 | option java_package = "com.alipay.antchain.bridge.pluginserver.managementservice";
7 | option java_outer_classname = "ManagementRpcServer";
8 |
9 | message PluginManageRequest{
10 | enum Type{
11 | // load all plugins in the default path
12 | LOAD_PLUGINS = 0;
13 | // start all plugins in the default path
14 | START_PLUGINS = 1;
15 | // load the specified plugin in the specified path
16 | LOAD_PLUGIN = 2;
17 | // start the specified plugin in the specified path
18 | START_PLUGIN = 3;
19 | // stop the specified plugin in the specified path
20 | STOP_PLUGIN = 4;
21 | // start the stopped plugin in the specified path
22 | START_PLUGIN_FROM_STOP = 5;
23 | // reload the specified plugin (plugin not started)
24 | RELOAD_PLUGIN = 6;
25 | // reload the specified plugin from the new path (plugin not started)
26 | RELOAD_PLUGIN_IN_NEW_PATH = 7;
27 | }
28 |
29 | Type type = 1;
30 | string path = 2;
31 | string product = 3;
32 | }
33 |
34 | message HasPluginsRequest{
35 | repeated string products = 1;
36 | }
37 |
38 | message AllPluginsRequest{
39 | }
40 |
41 | message HasDomainsRequest{
42 | repeated string domains = 1;
43 | }
44 |
45 | message AllDomainsRequest{
46 | }
47 |
48 | message RestartBBCRequest {
49 | string product = 1;
50 | string domain = 2;
51 | }
52 |
53 | message ManageResponse {
54 | uint32 code = 1;
55 | string errorMsg = 2;
56 | oneof manageResp {
57 | PluginManageResp pluginManageResp = 3;
58 | HasPluginsResp hasPluginsResp = 4;
59 | AllPluginsResp allPluginsResp = 5;
60 | HasDomainsResp hasDomainsResp = 6;
61 | AllDomainsResp allDomainsResp = 7;
62 | RestartBBCResp restartBBCResp = 8;
63 | }
64 | }
65 |
66 | message PluginManageResp{
67 | // stay empty body for now, maybe fill some stuff in future
68 | }
69 |
70 | message HasPluginsResp{
71 | // key : which product
72 | // value : support or not
73 | map results = 1;
74 | }
75 |
76 | message AllPluginsResp {
77 | repeated string products = 1;
78 | }
79 |
80 | message HasDomainsResp {
81 | // key : which chain
82 | // value : running or not
83 | map results = 1;
84 | }
85 |
86 | message AllDomainsResp {
87 | repeated string domains = 1;
88 | }
89 |
90 | message RestartBBCResp {
91 | }
92 |
93 | service ManagementService {
94 |
95 | // maintenance personnel may invoke this interface to load, unload, start, and stop plugins
96 | rpc managePlugin(PluginManageRequest) returns (ManageResponse) {}
97 |
98 | // return whether the plugins of the products are supported
99 | rpc hasPlugins(HasPluginsRequest) returns (ManageResponse) {}
100 |
101 | // return all supported plugin products
102 | rpc allPlugins(AllPluginsRequest) returns (ManageResponse) {}
103 |
104 | // return whether the chains of the domains are running
105 | rpc hasDomains(HasDomainsRequest) returns (ManageResponse) {}
106 |
107 | // return domains of all running chains
108 | rpc allDomains(AllDomainsRequest) returns (ManageResponse) {}
109 |
110 | // restart the bbc service object from the current plugin files
111 | rpc restartBBC(RestartBBCRequest) returns (ManageResponse) {}
112 | }
--------------------------------------------------------------------------------
/ps-service/src/main/proto/pluginserver.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package com.alipay.antchain.bridge.pluginserver.service;
4 |
5 | option java_multiple_files = true;
6 | option java_package = "com.alipay.antchain.bridge.pluginserver.service";
7 | option java_outer_classname = "PluginRpcServer";
8 |
9 | // just empty
10 | message Empty {}
11 |
12 | service CrossChainService {
13 | // Relayer would call this interface to communicate with the `BBCService` object
14 | rpc bbcCall(CallBBCRequest) returns (Response) {}
15 |
16 | // handle heartbeat requests from relayers
17 | rpc heartbeat(Empty) returns (Response) {}
18 |
19 | // return if these blockchain products support or not
20 | rpc ifProductSupport(IfProductSupportRequest) returns (Response) {}
21 |
22 | // return if these blockchain domains alive or not
23 | rpc ifDomainAlive(IfDomainAliveRequest) returns (Response) {}
24 | }
25 |
26 | // heartbeat response
27 | message HeartbeatResponse {
28 | repeated string products = 1;
29 | repeated string domains = 2;
30 | }
31 |
32 | message IfProductSupportRequest {
33 | repeated string products = 1;
34 | }
35 |
36 | message IfProductSupportResponse {
37 | // key : which product
38 | // value : support or not
39 | map results = 1;
40 | }
41 |
42 | message IfDomainAliveRequest {
43 | repeated string domains = 1;
44 | }
45 |
46 | message IfDomainAliveResponse {
47 | // key : which domain
48 | // value : alive or not
49 | map results = 1;
50 | }
51 |
52 | // wrapper for all responses
53 | message Response {
54 | uint32 code = 1;
55 | string errorMsg = 2;
56 | oneof response {
57 | CallBBCResponse bbcResp = 3;
58 | HeartbeatResponse heartbeatResp = 4;
59 | IfProductSupportResponse ifProductSupportResp = 5;
60 | IfDomainAliveResponse ifDomainAliveResp = 6;
61 | }
62 | }
63 |
64 | // messages for `bbcCall` requests
65 | message CallBBCRequest {
66 | // which kind of blockchain for plugin to load
67 | string product = 1;
68 |
69 | // which domain of the blockchain for the `BBCService` to connect with
70 | string domain = 2;
71 |
72 | // biz request for `BBCService`
73 | // basically, evey interface of `BBCService` has a request message defined here.
74 | oneof request {
75 | StartUpRequest startUpReq = 3;
76 | GetContextRequest getContextReq = 4;
77 | ShutdownRequest shutdownReq = 5;
78 | SetupAuthMessageContractRequest setupAuthMessageContractReq = 6;
79 | SetupSDPMessageContractRequest setupSDPMessageContractReq = 7;
80 | SetProtocolRequest setProtocolReq = 8;
81 | RelayAuthMessageRequest relayAuthMessageReq = 9;
82 | SetAmContractRequest setAmContractReq = 10;
83 | ReadCrossChainMessageReceiptRequest readCrossChainMessageReceiptReq = 11;
84 | ReadCrossChainMessagesByHeightRequest readCrossChainMessagesByHeightReq = 12;
85 | QuerySDPMessageSeqRequest querySDPMessageSeqReq = 13;
86 | QueryLatestHeightRequest queryLatestHeightReq = 14;
87 | SetLocalDomainRequest setLocalDomainReq = 15;
88 | }
89 | }
90 |
91 | message StartUpRequest {
92 | bytes rawContext = 1;
93 | }
94 |
95 | message GetContextRequest {
96 | // stay empty body for now, maybe fill some stuff in future
97 | }
98 |
99 | message ShutdownRequest {
100 | // stay empty body for now, maybe fill some stuff in future
101 | }
102 |
103 | message SetupAuthMessageContractRequest {
104 | // stay empty body for now, maybe fill some stuff in future
105 | }
106 |
107 | message SetupSDPMessageContractRequest {
108 | // stay empty body for now, maybe fill some stuff in future
109 | }
110 |
111 | message SetProtocolRequest {
112 | string protocolAddress = 1;
113 | string protocolType = 2;
114 | }
115 |
116 | message RelayAuthMessageRequest {
117 | bytes rawMessage = 1;
118 | }
119 |
120 | message SetAmContractRequest {
121 | string contractAddress = 1;
122 | }
123 |
124 | message ReadCrossChainMessageReceiptRequest {
125 | string txhash = 1;
126 | }
127 |
128 | message ReadCrossChainMessagesByHeightRequest {
129 | uint64 height = 1;
130 | }
131 |
132 | message QuerySDPMessageSeqRequest {
133 | string senderDomain = 1;
134 | string fromAddress = 2;
135 | string receiverDomain = 3;
136 | string toAddress = 4;
137 | }
138 |
139 | message QueryLatestHeightRequest {
140 | // stay empty body for now, maybe fill some stuff in future
141 | }
142 |
143 | message SetLocalDomainRequest {
144 | string domain = 1;
145 | }
146 |
147 | // basic messages.
148 | // same as project `antchain-bridge-commons`
149 | message CrossChainMessageReceipt {
150 | string txhash = 1;
151 | bool confirmed = 2;
152 | bool successful = 3;
153 | string errorMsg = 4;
154 | }
155 |
156 | enum CrossChainMessageType {
157 | AUTH_MSG = 0;
158 | DEVELOPER_DESIGN = 1;
159 | }
160 |
161 | message ProvableLedgerData {
162 | uint64 height = 1;
163 | bytes blockHash = 2;
164 | uint64 timestamp = 3;
165 | bytes ledgerData = 4;
166 | bytes proof = 5;
167 | bytes txHash = 6;
168 | }
169 |
170 | message CrossChainMessage {
171 | CrossChainMessageType type = 1;
172 | bytes message = 2;
173 | ProvableLedgerData provableData = 3;
174 | }
175 |
176 | // messages for `bbcCall` responses
177 | message CallBBCResponse {
178 | oneof response {
179 | GetContextResponse getContextResp = 1;
180 | SetupAuthMessageContractResponse setupAMResp = 2;
181 | SetupSDPMessageContractResponse setupSDPResp = 3;
182 | ReadCrossChainMessageReceiptResponse readCrossChainMessageReceiptResp = 4;
183 | ReadCrossChainMessagesByHeightResponse readCrossChainMessagesByHeightResp = 5;
184 | QuerySDPMessageSeqResponse querySDPMsgSeqResp = 6;
185 | RelayAuthMessageResponse relayAuthMessageResponse = 7;
186 | QueryLatestHeightResponse queryLatestHeightResponse = 8;
187 | }
188 | }
189 |
190 | message GetContextResponse {
191 | bytes rawContext = 1;
192 | }
193 |
194 | enum ContractStatusEnum {
195 | INIT = 0;
196 | CONTRACT_DEPLOYED = 1;
197 | CONTRACT_READY = 2;
198 | CONTRACT_FREEZE = 3;
199 | }
200 |
201 | message AuthMessageContract {
202 | string contractAddress = 1;
203 | ContractStatusEnum status = 2;
204 | }
205 |
206 | message SetupAuthMessageContractResponse {
207 | AuthMessageContract amContract = 1;
208 | }
209 |
210 | message SDPMessageContract {
211 | string contractAddress = 1;
212 | ContractStatusEnum status = 2;
213 | }
214 |
215 | message SetupSDPMessageContractResponse {
216 | SDPMessageContract sdpContract = 1;
217 | }
218 |
219 | message ReadCrossChainMessageReceiptResponse {
220 | CrossChainMessageReceipt receipt = 1;
221 | }
222 |
223 | message ReadCrossChainMessagesByHeightResponse {
224 | repeated CrossChainMessage messageList = 1;
225 | }
226 |
227 | message QuerySDPMessageSeqResponse {
228 | uint64 sequence = 1;
229 | }
230 |
231 | message RelayAuthMessageResponse {
232 | CrossChainMessageReceipt receipt = 1;
233 | }
234 |
235 | message QueryLatestHeightResponse {
236 | uint64 height = 1;
237 | }
--------------------------------------------------------------------------------