├── .github └── workflows │ └── azure-static-web-apps-white-coast-026e7af10.yml ├── .gitignore ├── README.md ├── UPDATE.md ├── img ├── 1.jpg └── 2.jpg ├── server ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── core │ ├── README.md │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── router │ │ │ ├── DebugCore.java │ │ │ ├── analysts │ │ │ ├── ArrayAnalysts.java │ │ │ ├── IAnalysts.java │ │ │ ├── IThreadAnalysts.java │ │ │ ├── InvokeUtils.java │ │ │ ├── ListAnalysts.java │ │ │ ├── MapAnalysts.java │ │ │ ├── ObjAnalysts.java │ │ │ └── SetAnalysts.java │ │ │ ├── breakpoint │ │ │ ├── BreakPointUtils.java │ │ │ └── MethodPoint.java │ │ │ ├── context │ │ │ ├── CacheContext.java │ │ │ └── Context.java │ │ │ ├── except │ │ │ ├── FieldExcept.java │ │ │ ├── FrameworkExcept.java │ │ │ ├── MethodExcept.java │ │ │ └── MiddleWareError.java │ │ │ ├── handler │ │ │ ├── BreakPointHandler.java │ │ │ ├── FrameworkHandler.java │ │ │ ├── Jersey1Handler.java │ │ │ ├── Jersey2Handler.java │ │ │ ├── SpringMvcHandler.java │ │ │ ├── Struts1Handler.java │ │ │ └── Struts2Handler.java │ │ │ ├── mapping │ │ │ ├── FilterMapping.java │ │ │ ├── FrameworkMapping.java │ │ │ ├── MiddlewareMapping.java │ │ │ └── ServletMapping.java │ │ │ ├── middleware │ │ │ ├── JettyMiddleware.java │ │ │ └── TomcatMiddleware.java │ │ │ ├── parse │ │ │ ├── UrlParse.java │ │ │ └── UrlType.java │ │ │ ├── pipeline │ │ │ ├── FilterPipeLine.java │ │ │ └── ServletPipeLine.java │ │ │ ├── publish │ │ │ ├── EndEvent.java │ │ │ ├── Error.java │ │ │ ├── ErrorEvent.java │ │ │ ├── ErrorType.java │ │ │ ├── Event.java │ │ │ ├── EventType.java │ │ │ ├── IPublish.java │ │ │ ├── StartEvent.java │ │ │ └── StdOutPublish.java │ │ │ ├── type │ │ │ ├── HandlerType.java │ │ │ └── MiddlewareType.java │ │ │ └── utils │ │ │ └── SpringUtils.java │ │ └── test │ │ └── java │ │ └── Test.java ├── mvnw ├── mvnw.cmd ├── pom.xml └── server │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── router │ │ └── server │ │ ├── RouterServerApplication.java │ │ ├── config │ │ ├── CorsConfig.java │ │ ├── CorsFilter.java │ │ ├── DataBaseConfig.java │ │ └── WebsocketConfig.java │ │ ├── context │ │ └── DatabaseContext.java │ │ ├── controller │ │ ├── ApiResponse.java │ │ ├── DataController.java │ │ ├── IndexController.java │ │ ├── LogController.java │ │ ├── ManagerController.java │ │ ├── ProgressController.java │ │ ├── ProjectCallback.java │ │ ├── ProjectController.java │ │ └── TaskController.java │ │ ├── entity │ │ ├── FilterEntity.java │ │ ├── FrameworkEntity.java │ │ ├── HandlerEntity.java │ │ ├── LogEntity.java │ │ ├── MiddlewareEntity.java │ │ ├── ProjectEntity.java │ │ └── ServletEntity.java │ │ ├── handler │ │ └── ListToStringHandler.java │ │ ├── mapper │ │ ├── BaseMapper.java │ │ ├── FilterMapper.java │ │ ├── FrameworkMapper.java │ │ ├── HandlerMapper.java │ │ ├── MiddlewareMapper.java │ │ ├── ProjectMapper.java │ │ └── ServletMapper.java │ │ ├── publish │ │ ├── ProgressTask.java │ │ ├── ServerEncoder.java │ │ └── WsPublish.java │ │ └── service │ │ ├── ConnectService.java │ │ ├── ProgressService.java │ │ ├── ProjectService.java │ │ └── TaskService.java │ └── resources │ ├── application.properties │ ├── banner.txt │ ├── mapper │ ├── FilterMapper.xml │ ├── FrameworkMapper.xml │ ├── HandlerMapper.xml │ ├── MiddlewareMapper.xml │ ├── ProjectMapper.xml │ └── ServletMapper.xml │ ├── static │ ├── css │ │ ├── app.16e5396e.css │ │ └── chunk-vendors.ddc93c7c.css │ ├── favicon.ico │ ├── index.html │ └── js │ │ ├── app.315660ce.js │ │ ├── app.315660ce.js.map │ │ ├── chunk-vendors.8892c512.js │ │ └── chunk-vendors.8892c512.js.map │ └── templates │ └── index.html └── webfrontend ├── .browserslistrc ├── .gitignore ├── .npmrc ├── README.md ├── babel.config.js ├── package.json ├── pnpm-lock.yaml ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── api │ ├── data.ts │ ├── jdwp.ts │ ├── progress.ts │ ├── project.ts │ └── task.ts ├── assets │ └── logo.png ├── components │ ├── manager │ │ ├── FrameworkBox.vue │ │ ├── FrameworkData.vue │ │ ├── MgAside.vue │ │ ├── MgData.vue │ │ ├── MgHeader.vue │ │ ├── MiddlewareBox.vue │ │ ├── MiddlewareData.vue │ │ └── ProgressItem.vue │ └── project │ │ ├── CreateProjectItem.vue │ │ ├── ProjectBottom.vue │ │ ├── ProjectNameIcon.vue │ │ ├── ProjectProfiler.vue │ │ └── ProjectTitle.vue ├── config.ts ├── main.ts ├── router │ └── index.ts ├── shims-vue.d.ts ├── theme │ └── dark.css ├── utils │ └── requests.ts └── views │ ├── DashBoard.vue │ └── manger │ ├── Data.vue │ ├── Index.vue │ ├── Profile.vue │ └── Progress.vue ├── tsconfig.json └── vue.config.js /.github/workflows/azure-static-web-apps-white-coast-026e7af10.yml: -------------------------------------------------------------------------------- 1 | name: Azure Static Web Apps CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize, reopened, closed] 9 | branches: 10 | - main 11 | 12 | jobs: 13 | build_and_deploy_job: 14 | if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') 15 | runs-on: ubuntu-latest 16 | name: Build and Deploy Job 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | submodules: true 21 | lfs: false 22 | - name: Build And Deploy 23 | id: builddeploy 24 | uses: Azure/static-web-apps-deploy@v1 25 | with: 26 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_WHITE_COAST_026E7AF10 }} 27 | repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) 28 | action: "upload" 29 | ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### 30 | # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig 31 | app_location: "./webfrontend" # App source code path 32 | api_location: "" # Api source code path - optional 33 | output_location: "dist" # Built app content directory - optional 34 | ###### End of Repository/Build Configurations ###### 35 | 36 | close_pull_request_job: 37 | if: github.event_name == 'pull_request' && github.event.action == 'closed' 38 | runs-on: ubuntu-latest 39 | name: Close Pull Request Job 40 | steps: 41 | - name: Close Pull Request 42 | id: closepullrequest 43 | uses: Azure/static-web-apps-deploy@v1 44 | with: 45 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_WHITE_COAST_026E7AF10 }} 46 | action: "close" 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Router6 2 | 3 | ![](https://camo.githubusercontent.com/5e63684235558188b21b1bf830c45db86b45f570236d10f03a80172f9aac614d/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323032322f7376672f313539393937392f313636313233323537383937302d38383539393738662d343732372d343636622d616232652d3162383635376561336163322e737667) 4 | ![](https://img.shields.io/badge/vue-3-green) 5 | ![](https://img.shields.io/badge/springboot-2-green) 6 | 7 | ## 实时更新的工具:白盒代码审计 8 | 9 |     我将工作遇到所有的框架进行了打包,很多时候分析产品的框架比较繁琐,需要分析每一个API的逻辑。但是稍微大一点的产品,逻辑十分复杂,既然本地能下断点,是不是可以利用Java JDI做点什么? 10 | 11 | ## 究竟能做什么? 12 | 13 |  如果是真实的java web项目,这个工具并不能适用以下情况: 14 | 15 | 1. 在那些无法运行或者仅仅能访问却无法设置添加JDWP的远程调试程序 16 | 17 | 2. 静态代码 18 | 19 | 基于此上两个条件:我觉得你已经明白他能跑在什么地方了: 20 | 21 | 1. 你可以完全运行一个程序 22 | 23 | 2. 你可以完整地设置程序启动的参数并设置JDWP的调试参数 24 | 25 | 很显然,这是专门为一些比较大型的产品做分析的工具,因为一般大型的产品架构复杂,光看配置文件都要吐了,更可恶的是,很多情况,一些配置写在文件里,可是真实情况却是在代码中遭到了修改,我觉得这个工具可以做到把这些麻烦的问题解决掉。 26 | 27 | ## 环境需求 28 | 29 | + Java JDK11 30 | + 网络端口默认9090 31 | 32 | ## 更新情况 33 | 34 | [最新版的更新情况](./UPDATE.md) 35 | 36 | 37 | ## 使用 38 | 39 |  从6.0开始,任务的创建基于项目,项目仅仅区分每个软件的路由,这样工具能够管理多个软件的数据。 40 | 41 | ## 项目创建 42 | 43 | ![](img/1.jpg) 44 | 45 | **项目名** : 目标软件的自定义名称 46 | 47 | **主机**:目标软件JDWP的ip地址 48 | 49 | **端口**:目标软件JDWP的端口 50 | 51 | 52 | 53 | ## 监听分析 54 | 55 | ![](img/2.jpg) 56 | 57 | 58 | 59 | 必须保证连接的成功后,功能“开始分析”才能得以正常运行。 60 | -------------------------------------------------------------------------------- /UPDATE.md: -------------------------------------------------------------------------------- 1 | | Router6更新 | 2 | | -------------------------- | 3 | | 引入项目概念 | 4 | | 数据开始支持本地磁盘持久化 | 5 | | 引入进度状态 | 6 | 7 | | Router5更新(一次扫描,不再需要重复手动更新) | 8 | | ------------------------------------------- | 9 | | 重要更新,所有断点都是基于breakpoint | 10 | 11 | | Router4更新(第四代:解放双手) | 12 | | ------------------- | 13 | | 把最初的事件断点直接删除,不再等待断点 | 14 | | 在考虑是否引入内存获取字节码反编译功能 | 15 | 16 | | Router3更新(第三代:不断完善) | 17 | | ------------------------------------------------------------------------------ | 18 | | 去除基于调试事件跟踪定位,直接采用内存分析,不会导致页面产生严重的卡顿:(还是保存最初的事件断点,但是对象的分析不再根据事件分析) | 19 | | 提高了路由获取的广泛性,能够面对一些修改框架的产品,减少了遗漏路由(内存对象分析,已经不再关心框架每一个修改细节,除非产品把框架对象的字段修改) | 20 | | 继续支持Spring5/4/3 | 21 | | 全面兼容Struts2的主流版本(2.1以上),struts1.x | 22 | | 全面兼容jersey1和jersey2 | 23 | | 由于采用内存分析,解决Jetty各种Handle的组合问题 | 24 | | 采用内存分析不再触发invoke的调试方式,提高了响应速度(invoke调试方式需要远程JVM做代码执行) | 25 | | 切换为最低JDK11的环境要求,不再需要tools.jar引入,采用JDK模块引入 | 26 | 27 | | Router-Router更新情况(第二代:补充完善分析的逻辑) | 28 | | --------------------------------------------------------------- | 29 | | 全面兼容Spring5/4/3(不兼容3.0.0单一版本) | 30 | | 全面支持Spring三种路由模式:注解路由,简单映射路由,bean名称路由(第一代只能支持注解解析) | 31 | | 全面兼容Jetty的各Handle(默认的框架Handle,缺点:还是无法面对市场的千变万化的修改) | 32 | | 全面兼容Tomcat7/8/9 | 33 | | 新版本已经可以自动检索目标。不再需要手动干预(只是简单代替用户做HTTP请求,效果不佳) | 34 | | 更换Spring/Vue架构,不再出现操作系统的UI兼容性问题(基于B/S) | 35 | | 不再阻塞当前堆栈,真正实现无侵入式连接(老版会阻塞程序运行) | 36 | | 不再支持Resin中间件(遇到的比较少,不想挖坑) | 37 | | 新增功能:自动去除框架或中间的垃圾路由 | 38 | | 采用JDK8 | 39 | 40 | | Router Killer(第一代:定义架构) | 41 | | ---------------------------------------------- | 42 | | 兼容Spring5 | 43 | | 兼容jetty9(不兼容修改框架的产品) | 44 | | 兼容tomcat9/8(不兼容tomcat6/7) | 45 | | 兼容Resin(未经过大量产品代码审计的验证) | 46 | | 基于Java JDI 断点的事件分析(不适配修改框架的产品) | 47 | | 采用JDK8 | 48 | | 采用JAVA GUI进行开发(不熟悉API的使用,不兼容Mac) | 49 | | 需要用户参与:手动触发某个框架的路由查询断点才能分析(极其不智能) | 50 | | 无法处理垃圾路由(即一些默认的路由:/error) | 51 | 52 | ## 兼容的版本 53 | 54 | | Spring(框架) | Tomcat(中间件) | Jetty(中间件) | Struts(框架) | Jersey(我个人觉得是Rest插件) | 55 | | ----------------------------- | -------------- | -------------------------------- | ---------- | -------------------- | 56 | | 5.0.0.RELEASE-5.3.20 | 9.0.1-9.0.70 | 11.0.0 | 2.5.x | 2.0-2.39 | 57 | | 4.0.0.RELEASE-4.3.30.RELEASE | 8.0.1-8.5.81 | 10.0.0-10.0.10 | 2.3.x | 1.x | 58 | | 3.1.0.RELEASE, 3.2.18.RELEASE | 7.0.30-7.0.103 | 9.0.0.v20130308-9.4.50.v20221201 | 2.2.1 | | 59 | | | | | 1.x | | 60 | 61 | 以上是测试的版本,未测试版本不确定能否解析 62 | 63 | 确定不兼容的组合情况: 64 | 65 |     我并不打算支持tomcat6/7解析jersey/struts这样的古老组合,并且我不会支持Spring Mvc + jersey / struts。因为在我遇到的产品,根本没人这么干,jersey/struts更多的还是和中间件一起工作,而不是和spring Mvc。反向jersey/struts更多可能只是和Spring Core一起罢了,但是这在路由和映射类的获取上来说没有任何影响。 -------------------------------------------------------------------------------- /img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/img/1.jpg -------------------------------------------------------------------------------- /img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/img/2.jpg -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | route.db -------------------------------------------------------------------------------- /server/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/server/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar 19 | -------------------------------------------------------------------------------- /server/core/README.md: -------------------------------------------------------------------------------- 1 | # JDWP Route Core 2 | 库包只支持对JDWP中Value远程对象的分析。 基本用法如下: 3 | ```java 4 | 5 | ``` -------------------------------------------------------------------------------- /server/core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | kd.router 8 | router 9 | 6.0 10 | 11 | 12 | kd.router 13 | core 14 | 15 | 11 16 | 11 17 | UTF-8 18 | 19 | 20 | 21 | 22 | ch.qos.logback 23 | logback-classic 24 | provided 25 | 26 | 27 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/DebugCore.java: -------------------------------------------------------------------------------- 1 | package router; 2 | 3 | import com.sun.jdi.event.BreakpointEvent; 4 | import com.sun.jdi.event.Event; 5 | import com.sun.jdi.event.EventQueue; 6 | import com.sun.jdi.event.EventSet; 7 | import router.context.Context; 8 | import router.handler.BreakPointHandler; 9 | import router.breakpoint.BreakPointUtils; 10 | import com.sun.jdi.VirtualMachine; 11 | 12 | import java.util.Iterator; 13 | 14 | /** 15 | * DebugCore作为核心驱动 16 | */ 17 | public class DebugCore implements Runnable { 18 | private VirtualMachine vm; 19 | private Context context; 20 | private volatile boolean stop = false; // 退出标志 21 | 22 | public DebugCore() { 23 | } 24 | 25 | public static DebugCore build(VirtualMachine vm, Context context) { 26 | DebugCore debugCore = new DebugCore(); 27 | debugCore.vm = vm; 28 | debugCore.context = context; 29 | return debugCore; 30 | } 31 | 32 | 33 | /** 34 | * registryHandler 注册处理器 35 | * 36 | * @param className 监听类名 37 | * @param methodName 监听类名的具体方法 38 | * @param handler 监视后的事件处理接口 39 | */ 40 | public void registryHandler(String className, String methodName, BreakPointHandler handler) { 41 | BreakPointUtils.createMethodBreakPointFront(vm, className, methodName, handler); 42 | } 43 | 44 | @Override 45 | public void run() { 46 | while (!stop) { 47 | EventQueue eventQueue = vm.eventQueue(); 48 | EventSet events = null; 49 | try { 50 | events = eventQueue.remove(); 51 | } catch (Exception e) { 52 | if (!stop) { 53 | continue; 54 | } 55 | } 56 | assert events != null; 57 | for (Event event : events) { 58 | if (event instanceof BreakpointEvent) { 59 | BreakPointHandler handler = (BreakPointHandler) event.request().getProperty("handler"); 60 | handler.handler((BreakpointEvent) event, ((BreakpointEvent) event).thread(), context); 61 | context.completeTask(); 62 | vm.eventRequestManager().deleteAllBreakpoints(); 63 | vm.resume(); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public void stopTask() { 70 | stop = true; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/ArrayAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.ArrayReference; 4 | 5 | import java.util.Iterator; 6 | import java.util.Objects; 7 | 8 | /** 9 | * ArrayAnalysts对Java Array数组类型进行转化分析 10 | */ 11 | public class ArrayAnalysts extends ObjAnalysts implements Iterable { 12 | private ArrayReference value; 13 | private IAnalysts[] data; 14 | 15 | public ArrayAnalysts(IAnalysts objAnalysts) { 16 | init(objAnalysts.getRawValue()); 17 | if (!(getRawValue() instanceof ArrayReference)) { 18 | objValue = null; 19 | type = null; 20 | return; 21 | } 22 | this.thread = objAnalysts.getThreadRawRef(); 23 | value = (ArrayReference) getRawValue(); 24 | data = value.getValues().stream().filter(Objects::nonNull).map(e -> ObjAnalysts.parseObject(thread, e)).toArray(ObjAnalysts[]::new); 25 | } 26 | 27 | public IAnalysts get(int index) { 28 | return ObjAnalysts.parseObject(thread, value.getValue(index)); 29 | } 30 | 31 | public int size() { 32 | return data.length; 33 | } 34 | 35 | @Override 36 | public Iterator iterator() { 37 | return new ObjectIter(data); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/IAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.Value; 4 | import router.except.FieldExcept; 5 | import router.except.MethodExcept; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 此接口仅对Object类型进行封装增强,接口并不提供其他Java基础类型的封装增强 11 | * 需要注意的是,IAnalysts接口并不排斥基础类型,所以当用IAnalysts封装例如ByteType此类型时, 12 | * 并不会抛异常 13 | */ 14 | public interface IAnalysts extends IThreadAnalysts { 15 | 16 | /** 17 | * 获取Object对应的Value 18 | * 19 | * @return Value接口类型返回值可能是任意的实现类ArrayReference|ObjectReference... 20 | */ 21 | Value getRawValue(); 22 | 23 | /** 24 | * IAnalysts接口实现可以是任意的Java类型,比如String/Integer等,但是IAnalysts侧重Object 25 | * 所以提供isObjRef用于判断IAnalysts是否为Object类型的方法 26 | * 27 | * @return true|false,true表示此IAnalysts是Object类型 28 | */ 29 | boolean isObjRef(); 30 | 31 | /** 32 | * 用于获取Java的全限定类名 33 | * 34 | * @return IAnalysts对应的类名 35 | */ 36 | String getClassName(); 37 | 38 | /** 39 | * InstanceOf除了比较继承关系之外,如果比较对象的类型相同,一样返回true 40 | * 41 | * @param className java中的全限定类名,比如java.lang.String 42 | * @return true|false, 请注意!isInstanceof在比较对象时,如果A与B是同种类型,此时返回值也是true 43 | */ 44 | boolean isInstanceof(String className); 45 | 46 | /** 47 | * isImplementOf用于确定对象是否实现了特定的接口 48 | * 49 | * @param interfaceName 接口名称 50 | * @return boolean 51 | */ 52 | boolean isImplementOf(String interfaceName); 53 | 54 | /** 55 | * getObjFields用于获取对象的成员,支持多级调用。 56 | * 比如A类型有B、C成员,B成员对象有b对象,此时通过A.getFieldsRef('B','b')获取b成员 57 | * 58 | * @param fieldNames 59 | * @return IAnalysts成员 60 | */ 61 | IAnalysts getObjFields(String... fieldNames) throws FieldExcept; 62 | 63 | /** 64 | * getId对于一次远程调试,每一个Remote Object都有一个唯一ID 65 | * @return Object unique ID 66 | */ 67 | Long getId(); 68 | 69 | /** 70 | * 与getObjFields类型,但是getStrFields不会把结果类型通过IAnalysts封装返回 71 | * 72 | * @param fieldNames 73 | * @return String 74 | * @throws Exception 75 | */ 76 | String getStrFields(String... fieldNames) throws FieldExcept; 77 | 78 | Integer getIntFields(String... fieldNames) throws FieldExcept; 79 | 80 | byte getByteFields(String... fieldNames) throws FieldExcept; 81 | 82 | boolean getBoolFields(String... fieldNames) throws FieldExcept; 83 | 84 | char getCharFields(String... fieldNames) throws FieldExcept; 85 | 86 | double getDoubleFields(String... fieldNames) throws FieldExcept; 87 | 88 | float getFloatFields(String... fieldNames) throws FieldExcept; 89 | 90 | long getLongFields(String... fieldNames) throws FieldExcept; 91 | 92 | short getShortFields(String... fieldNames) throws FieldExcept; 93 | 94 | /** 95 | * existFieldByName用于判断对象是否存在某个成员,支持多级调用。 96 | * 97 | * @param fieldNames 成员名称(多级成员) 98 | * @return boolean 99 | */ 100 | boolean existFieldByName(String... fieldNames); 101 | 102 | /** 103 | * 此方法只限定用于远程Value对象类型为String的情况下 104 | * 105 | * @return String 106 | * @throws Exception 107 | */ 108 | String convertToString() throws Exception; 109 | 110 | 111 | IAnalysts invokeMethodDesc(String method, String desc) throws MethodExcept; 112 | 113 | IAnalysts invokeMethodDescArgs(String method, String desc, List args) throws MethodExcept; 114 | 115 | IAnalysts invokeMethod(String method) throws MethodExcept; 116 | 117 | IAnalysts invokeMethodArgs(String method, List args) throws MethodExcept; 118 | 119 | String getPackageVersion(String packageName); 120 | 121 | } 122 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/IThreadAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.*; 4 | 5 | /** 6 | * IThreadAnalysts仅提供线程级别的功能,Object需要实现此接口 7 | */ 8 | public interface IThreadAnalysts { 9 | 10 | /** 11 | * getThreadRawRef用于返回当前线程的ThreadReference远程对象 12 | * @return ThreadReference 13 | */ 14 | ThreadReference getThreadRawRef(); 15 | 16 | /** 17 | * 此方法用于获取当前线程的ClassLoader 18 | * 19 | * @return IAnalysts内部ClassLoaderReference 20 | */ 21 | IAnalysts getCurrentThreadClassLoader() throws Exception; 22 | 23 | 24 | /** 25 | * 此方法用于切换当前加载 26 | * 27 | * @param classLoader 此参数的IAnalysts内部封装对象必须是ClassLoaderReference 28 | */ 29 | void changeThreadClassLoader(IAnalysts classLoader) throws Exception; 30 | } 31 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/InvokeUtils.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | 4 | import com.sun.jdi.*; 5 | import router.except.FieldExcept; 6 | import router.except.MethodExcept; 7 | 8 | import java.util.*; 9 | 10 | import static java.util.Collections.EMPTY_LIST; 11 | 12 | public class InvokeUtils { 13 | public static IAnalysts invokeMethod(ObjAnalysts objRef, String methodName, String desc, List args) throws MethodExcept { 14 | ThreadReference frameThread = objRef.getThreadRawRef(); 15 | return ObjAnalysts.parseObject(frameThread, 16 | nativeInvokeMethod(objRef.getThreadRawRef(), objRef.objValue, methodName, desc, args)); 17 | } 18 | 19 | public static IAnalysts invokeMethodSingle(ObjAnalysts obj, String methodName, List args) throws MethodExcept { 20 | return ObjAnalysts.parseObject(obj.getThreadRawRef(), nativeInvokeMethodSingle(obj.getThreadRawRef(), obj.objValue, methodName, args)); 21 | } 22 | 23 | public static IAnalysts invokeMethodSingleNoArgs(ObjAnalysts obj, String methodName) throws MethodExcept { 24 | return ObjAnalysts.parseObject(obj.getThreadRawRef(), nativeInvokeMethodSingleNoArgs(obj.getThreadRawRef(), obj.objValue, methodName)); 25 | } 26 | 27 | public static Value nativeInvokeMethodSingle(ThreadReference thread, ObjectReference objRef, String methodName, List args) throws MethodExcept { 28 | Method method = objRef.referenceType().methodsByName(methodName).get(0); 29 | try { 30 | return objRef.invokeMethod(thread, method, args, ObjectReference.INVOKE_SINGLE_THREADED); 31 | } catch (Exception e) { 32 | throw new MethodExcept(methodName); 33 | } 34 | } 35 | 36 | public static Value nativeInvokeMethod(ThreadReference thead, ObjectReference objRef, String methodName, String desc, List args) throws MethodExcept { 37 | Method method = objRef.referenceType().methodsByName(methodName, desc).get(0); 38 | if (method == null) { 39 | return null; 40 | } 41 | try { 42 | return objRef.invokeMethod(thead, method, args, ObjectReference.INVOKE_SINGLE_THREADED); 43 | } catch (Exception e) { 44 | throw new MethodExcept(methodName); 45 | } 46 | } 47 | 48 | public static Value nativeInvokeMethodSingleNoArgs(ThreadReference thread, ObjectReference objRef, String methodName) throws MethodExcept { 49 | return nativeInvokeMethodSingle(thread, objRef, methodName, EMPTY_LIST); 50 | } 51 | 52 | public static Value getFieldObject(ObjectReference value, String fieldString) throws FieldExcept { 53 | Field field = null; 54 | try { 55 | field = value.referenceType().fieldByName(fieldString); 56 | } catch (Exception e) { 57 | for (Field allField : value.referenceType().allFields()) { 58 | System.out.println(allField.name()); 59 | } 60 | throw new FieldExcept(value, fieldString); 61 | } 62 | return value.getValue(field); 63 | } 64 | 65 | public static Value getFieldOneByOne(Value objectReference, String... fields) throws FieldExcept { 66 | ObjectReference tmp = (ObjectReference) objectReference; 67 | for (String field : fields) { 68 | tmp = (ObjectReference) getFieldObject(tmp, field); 69 | if (tmp == null) { 70 | return null; 71 | } 72 | } 73 | return tmp; 74 | } 75 | 76 | public static HashMap getMap(ThreadReference thread, ObjectReference objRef) throws MethodExcept { 77 | HashMap result = new HashMap<>(); 78 | Value keySetRef = nativeInvokeMethodSingleNoArgs(thread, objRef, "keySet"); 79 | if (keySetRef == null) { 80 | return null; 81 | } 82 | Value elems = nativeInvokeMethod(thread, (ObjectReference) keySetRef, "toArray", "()[Ljava/lang/Object;", EMPTY_LIST); 83 | if (elems == null) { 84 | return null; 85 | } 86 | for (Value elem : ((ArrayReference) elems).getValues()) { 87 | ArrayList args = new ArrayList<>(); 88 | args.add(elem); 89 | Value value = nativeInvokeMethod(thread, objRef, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", args); 90 | result.put(elem, value); 91 | } 92 | return result; 93 | } 94 | 95 | public static ArrayReference getMapValue(ThreadReference thread, ObjectReference objRef) throws MethodExcept { 96 | Value values = nativeInvokeMethodSingleNoArgs(thread, objRef, "values"); 97 | if (values == null) { 98 | return null; 99 | } 100 | return (ArrayReference) nativeInvokeMethod(thread, (ObjectReference) values, "toArray", "()[Ljava/lang/Object;", EMPTY_LIST); 101 | } 102 | 103 | public static HashSet getSet(ThreadReference thread, ObjectReference objRef) throws MethodExcept { 104 | HashSet result = new HashSet<>(); 105 | ArrayReference value = (ArrayReference) nativeInvokeMethod(thread, objRef, "toArray", "()[Ljava/lang/Object;", EMPTY_LIST); 106 | result.addAll(value.getValues()); 107 | return result; 108 | } 109 | 110 | public static List getList(ThreadReference thread, ObjectReference objRef) throws MethodExcept { 111 | ArrayReference value = (ArrayReference) nativeInvokeMethod(thread, objRef, "toArray", "()[Ljava/lang/Object;", EMPTY_LIST); 112 | if (value == null) { 113 | return null; 114 | } 115 | return value.getValues(); 116 | } 117 | 118 | public static boolean isInstance(String parentClassName, ObjectReference obj) { 119 | String subClassName = obj.referenceType().name(); 120 | List referenceTypes = obj.virtualMachine().classesByName(parentClassName); 121 | for (ReferenceType referenceType : referenceTypes) { 122 | if (((ClassType) referenceType).subclasses().stream().anyMatch(e -> e.name().equals(subClassName))) { 123 | return true; 124 | } 125 | } 126 | return false; 127 | } 128 | 129 | public static boolean isImplementOf(String interfaceName, ObjectReference obj) { 130 | if (obj == null) { 131 | return false; 132 | } 133 | List referenceTypes = obj.virtualMachine().classesByName(obj.referenceType().name()); 134 | for (ReferenceType referenceType : referenceTypes) { 135 | if (((ClassType) referenceType).allInterfaces().stream().anyMatch(i -> i.name().equals(interfaceName))) { 136 | return true; 137 | } 138 | } 139 | return false; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/ListAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.ObjectReference; 4 | import com.sun.jdi.ThreadReference; 5 | import com.sun.jdi.Value; 6 | import router.publish.IPublish; 7 | 8 | import java.util.Arrays; 9 | import java.util.Iterator; 10 | import java.util.stream.Stream; 11 | 12 | 13 | public class ListAnalysts extends ObjAnalysts implements Iterable { 14 | public ListAnalysts(IAnalysts obj) { 15 | getList(obj.getThreadRawRef(), obj.getRawValue()); 16 | } 17 | 18 | private IAnalysts[] data; 19 | 20 | private void getList(ThreadReference thread, Value obj) { 21 | init(obj); 22 | if (isImplementOf("java.util.List")) { 23 | return; 24 | } 25 | this.thread = thread; 26 | this.data = InvokeUtils.getList(thread, (ObjectReference) getRawValue()) 27 | .stream().map(elem -> ObjAnalysts.parseObject(thread, elem)) 28 | .toArray(IAnalysts[]::new); 29 | } 30 | 31 | public Stream stream() { 32 | return Arrays.stream(data); 33 | } 34 | 35 | public int size(){ 36 | return data.length; 37 | } 38 | 39 | @Override 40 | public Iterator iterator() { 41 | return new ObjectIter(data); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/MapAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.ObjectReference; 4 | import com.sun.jdi.ThreadReference; 5 | import com.sun.jdi.Value; 6 | import router.publish.IPublish; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | 11 | public class MapAnalysts extends ObjAnalysts { 12 | 13 | public MapAnalysts(IAnalysts obj) { 14 | getMap(obj.getThreadRawRef(), obj.getRawValue()); 15 | } 16 | 17 | private void getMap(ThreadReference thread, Value obj) { 18 | init(obj); 19 | this.thread = thread; 20 | } 21 | 22 | public Entry[] getKV() { 23 | HashMap map = InvokeUtils.getMap(thread, objValue); 24 | if (map != null) { 25 | ArrayList result = new ArrayList<>(); 26 | map.forEach((key, value) -> { 27 | result.add(Entry.create((ObjectReference) key, (ObjectReference) value, thread)); 28 | }); 29 | return result.toArray(Entry[]::new); 30 | } 31 | return null; 32 | } 33 | 34 | public IAnalysts[] getValues() { 35 | return InvokeUtils.getMapValue(thread, objValue) 36 | .getValues().stream().map(elem -> ObjAnalysts.parseObject(thread, elem)).toArray(ObjAnalysts[]::new); 37 | } 38 | 39 | public static class Entry { 40 | private IAnalysts key; 41 | private IAnalysts value; 42 | 43 | protected static Entry create(ObjectReference key, ObjectReference value, ThreadReference threadReference) { 44 | return new Entry(ObjAnalysts.parseObject(threadReference, key), ObjAnalysts.parseObject(threadReference, value)); 45 | } 46 | 47 | public Entry(IAnalysts key, IAnalysts value) { 48 | this.key = key; 49 | this.value = value; 50 | } 51 | 52 | public IAnalysts getKey() { 53 | return key; 54 | } 55 | 56 | public IAnalysts getValue() { 57 | return value; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/analysts/SetAnalysts.java: -------------------------------------------------------------------------------- 1 | package router.analysts; 2 | 3 | import com.sun.jdi.ObjectReference; 4 | import com.sun.jdi.ThreadReference; 5 | import com.sun.jdi.Value; 6 | import router.publish.IPublish; 7 | 8 | import java.util.Iterator; 9 | 10 | /** 11 | * SetAnalyst对Java Set集合类转化分析 12 | */ 13 | public class SetAnalysts extends ObjAnalysts implements Iterable { 14 | 15 | public SetAnalysts(IAnalysts obj) { 16 | getSet(obj.getThreadRawRef(), obj.getRawValue()); 17 | } 18 | 19 | protected IAnalysts[] data; 20 | 21 | public void getSet(ThreadReference thread, Value obj) { 22 | init(obj); 23 | if (isImplementOf("java.util.Set")) { 24 | return; 25 | } 26 | this.thread = thread; 27 | this.data = InvokeUtils.getSet(thread, (ObjectReference) getRawValue()) 28 | .stream() 29 | .map(elem -> ObjAnalysts.parseObject(thread, elem)) 30 | .toArray(ObjAnalysts[]::new); 31 | } 32 | 33 | public int size(){ 34 | return data.length; 35 | } 36 | 37 | 38 | @Override 39 | public Iterator iterator() { 40 | return new ObjectIter(data); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/breakpoint/BreakPointUtils.java: -------------------------------------------------------------------------------- 1 | package router.breakpoint; 2 | 3 | import com.sun.jdi.*; 4 | import com.sun.jdi.request.BreakpointRequest; 5 | import com.sun.jdi.request.ClassPrepareRequest; 6 | import com.sun.jdi.request.EventRequest; 7 | import router.handler.BreakPointHandler; 8 | 9 | import java.util.List; 10 | 11 | public class BreakPointUtils { 12 | private static boolean internalCreateMethodBreakPoint(VirtualMachine vm, MethodPoint methodPoint, int point) { 13 | String className = methodPoint.getClassName(); 14 | String methodName = methodPoint.getMethodName(); 15 | BreakPointHandler handler = methodPoint.getHandler(); 16 | 17 | List referenceTypes = vm.classesByName(className); 18 | if (referenceTypes.isEmpty()) { 19 | return false; 20 | } 21 | ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest(); 22 | classPrepareRequest.addClassFilter(className); 23 | classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); 24 | classPrepareRequest.enable(); 25 | 26 | for (ReferenceType elem : referenceTypes) { 27 | List methods = elem.methodsByName(methodName); 28 | if (!methods.isEmpty()) { 29 | Method method = methods.get(0); 30 | try { 31 | List locations = method.allLineLocations(); 32 | Location location = null; 33 | if (point == 0) { 34 | location = locations.get(0); 35 | BreakpointRequest breakpointRequest = vm.eventRequestManager().createBreakpointRequest(location); 36 | breakpointRequest.putProperty("handler", handler); 37 | breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 38 | breakpointRequest.enable(); 39 | } else if (point == 1) { 40 | location = locations.get(locations.size() - 1); 41 | BreakpointRequest breakpointRequest = vm.eventRequestManager().createBreakpointRequest(location); 42 | breakpointRequest.putProperty("handler", handler); 43 | breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 44 | breakpointRequest.enable(); 45 | location = locations.get(0); 46 | } else { 47 | Location first = locations.get(0); 48 | Location last = locations.get(locations.size() - 1); 49 | BreakpointRequest breakpointRequest = vm.eventRequestManager().createBreakpointRequest(first); 50 | breakpointRequest.putProperty("handler", handler); 51 | breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 52 | breakpointRequest.enable(); 53 | breakpointRequest = vm.eventRequestManager().createBreakpointRequest(last); 54 | breakpointRequest.putProperty("handler", handler); 55 | breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 56 | breakpointRequest.enable(); 57 | } 58 | } catch (AbsentInformationException e) { 59 | throw new RuntimeException(e); 60 | } 61 | } 62 | } 63 | return true; 64 | } 65 | 66 | public static void createMethodBreakPointFront(VirtualMachine virtualMachine, String className, String methodName, BreakPointHandler handler) { 67 | internalCreateMethodBreakPoint(virtualMachine, new MethodPoint(className, methodName, handler), 0); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/breakpoint/MethodPoint.java: -------------------------------------------------------------------------------- 1 | package router.breakpoint; 2 | 3 | import router.handler.BreakPointHandler; 4 | 5 | import java.util.Objects; 6 | 7 | public class MethodPoint { 8 | private String className; 9 | private String methodName; 10 | private BreakPointHandler handler; 11 | 12 | public MethodPoint(String className, String methodName, BreakPointHandler handler) { 13 | this.className = className; 14 | this.methodName = methodName; 15 | this.handler = handler; 16 | } 17 | 18 | public String getClassName() { 19 | return className; 20 | } 21 | 22 | public void setClassName(String className) { 23 | this.className = className; 24 | } 25 | 26 | public String getMethodName() { 27 | return methodName; 28 | } 29 | 30 | public void setMethodName(String methodName) { 31 | this.methodName = methodName; 32 | } 33 | 34 | public BreakPointHandler getHandler() { 35 | return handler; 36 | } 37 | 38 | public void setHandler(BreakPointHandler handler) { 39 | this.handler = handler; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (o == null || getClass() != o.getClass()) return false; 46 | MethodPoint that = (MethodPoint) o; 47 | return Objects.equals(className, that.className) && Objects.equals(methodName, that.methodName); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(className, methodName); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/context/CacheContext.java: -------------------------------------------------------------------------------- 1 | package router.context; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.mapping.FilterMapping; 5 | import router.mapping.FrameworkMapping; 6 | import router.mapping.MiddlewareMapping; 7 | import router.mapping.ServletMapping; 8 | import router.publish.IPublish; 9 | import router.type.HandlerType; 10 | import router.type.MiddlewareType; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.LinkedList; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | public class CacheContext implements Context { 19 | public List middlewareCache; 20 | public List frameworkCache; 21 | public HashMap servletCache; 22 | public LinkedList filterCache; 23 | public HashMap analystCache; 24 | public IPublish publish; 25 | 26 | public static CacheContext build(IPublish publish) { 27 | CacheContext cacheContext = new CacheContext(); 28 | cacheContext.filterCache = new LinkedList<>(); 29 | cacheContext.middlewareCache = new ArrayList<>(); 30 | cacheContext.frameworkCache = new ArrayList<>(); 31 | cacheContext.servletCache = new HashMap<>(); 32 | cacheContext.analystCache = new HashMap<>(); 33 | cacheContext.publish = publish; 34 | return cacheContext; 35 | } 36 | 37 | 38 | @Override 39 | public void pushMiddleware(MiddlewareMapping middleware) { 40 | middlewareCache.add(middleware); 41 | } 42 | 43 | @Override 44 | public void pushFramework(FrameworkMapping framework) { 45 | frameworkCache.add(framework); 46 | } 47 | 48 | @Override 49 | public void completeTask(){} 50 | 51 | @Override 52 | public IPublish getPublish() { 53 | return publish; 54 | } 55 | 56 | @Override 57 | public void pushAnalysts(IAnalysts analysts) { 58 | analystCache.put(analysts.getId(), analysts); 59 | } 60 | 61 | @Override 62 | public IAnalysts getAnalystsByUniqId(Long id) { 63 | return analystCache.get(id); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/context/Context.java: -------------------------------------------------------------------------------- 1 | package router.context; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.mapping.FrameworkMapping; 5 | import router.mapping.MiddlewareMapping; 6 | import router.publish.IPublish; 7 | import router.type.HandlerType; 8 | import router.type.MiddlewareType; 9 | 10 | import java.rmi.server.RemoteObject; 11 | import java.util.List; 12 | 13 | 14 | /** 15 | * Context代表一个调试过程中相关的内容 16 | */ 17 | public interface Context { 18 | 19 | /** 20 | * 存储中间件对象 21 | * 22 | * @param middleware 23 | */ 24 | void pushMiddleware(MiddlewareMapping middleware); 25 | 26 | /** 27 | * 存储框架对象 28 | * 29 | * @param framework 30 | */ 31 | void pushFramework(FrameworkMapping framework); 32 | 33 | /** 34 | * 标志一个任务的结束 35 | */ 36 | void completeTask(); 37 | 38 | /** 39 | * 获取一个公布器 40 | * 41 | * @return 42 | */ 43 | IPublish getPublish(); 44 | 45 | /** 46 | * 存储一个远程对象 47 | */ 48 | void pushAnalysts(IAnalysts analysts); 49 | 50 | IAnalysts getAnalystsByUniqId(Long id); 51 | } 52 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/except/FieldExcept.java: -------------------------------------------------------------------------------- 1 | package router.except; 2 | 3 | import com.sun.jdi.ObjectReference; 4 | 5 | public class FieldExcept extends Exception { 6 | public FieldExcept(ObjectReference obj, String field) { 7 | super("not exist field: " + field + " in " + obj.referenceType().name()); 8 | } 9 | 10 | public FieldExcept(String field) { 11 | super(field); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/except/FrameworkExcept.java: -------------------------------------------------------------------------------- 1 | package router.except; 2 | 3 | public class FrameworkExcept extends Exception{ 4 | public FrameworkExcept(String message){ 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/except/MethodExcept.java: -------------------------------------------------------------------------------- 1 | package router.except; 2 | 3 | public class MethodExcept extends RuntimeException { 4 | public MethodExcept(String message) { 5 | super("remote call method fail: " + message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/except/MiddleWareError.java: -------------------------------------------------------------------------------- 1 | package router.except; 2 | 3 | public class MiddleWareError extends Exception{ 4 | public MiddleWareError(String msg){ 5 | super(msg); 6 | } 7 | 8 | public static MiddleWareError TomcatError(String msg){ 9 | return new MiddleWareError("Tomcat Error Event:[ " + msg + " ]"); 10 | } 11 | 12 | public static MiddleWareError JettyError(String msg){ 13 | return new MiddleWareError("Jetty Error Event:[ " + msg + " ]"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/BreakPointHandler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | 4 | import com.sun.jdi.IncompatibleThreadStateException; 5 | import com.sun.jdi.ThreadReference; 6 | import com.sun.jdi.event.BreakpointEvent; 7 | import router.analysts.IAnalysts; 8 | import router.analysts.ObjAnalysts; 9 | import router.context.Context; 10 | import router.except.MiddleWareError; 11 | import router.publish.*; 12 | import router.publish.Error; 13 | import router.type.MiddlewareType; 14 | 15 | public interface BreakPointHandler { 16 | default void handler(BreakpointEvent breakpointEvent, ThreadReference thread, Context context) { 17 | if (breakpointEvent.thread().isSuspended()) { 18 | IAnalysts thisObject = getThisObject(thread); 19 | try { 20 | handlerTarget(thisObject, context); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * 这里处理的是每一个上下文容器,tomcat中存在多个contextObjectToContextVersionMaps,每一个对象只进行一次分析 29 | * 这里需要注意一点,在进行handlerTarget调用中,会默认初始化所有的Servlet,这意味着不存在load-on-startup导致的Servlet不存在的问题,这样就确保在第一次访问时,就能完成所有分析 30 | * 详细初始化问题,在initServlet()中可见 31 | * 32 | * @param thisObject 33 | * @param context 34 | * @throws MiddleWareError 35 | */ 36 | void handlerTarget(IAnalysts thisObject, Context context) throws MiddleWareError; 37 | 38 | default IAnalysts getThisObject(ThreadReference ref) { 39 | try { 40 | return ObjAnalysts.parseObject(ref, ref.frame(0).thisObject()); 41 | } catch (IncompatibleThreadStateException e) { 42 | throw new RuntimeException(e); 43 | } 44 | } 45 | 46 | MiddlewareType getHandlerName(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/FrameworkHandler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.context.Context; 5 | import router.mapping.FrameworkMapping; 6 | import router.except.FrameworkExcept; 7 | import router.parse.UrlParse; 8 | import router.publish.*; 9 | import router.type.HandlerType; 10 | 11 | public interface FrameworkHandler { 12 | default void handler(UrlParse urlParse, IAnalysts objRef, Context context) { 13 | if (context.getAnalystsByUniqId(objRef.getId()) ==null){ 14 | context.pushAnalysts(objRef); 15 | }else{ 16 | return; 17 | } 18 | FrameworkMapping frameworkMapping = new FrameworkMapping(); 19 | String packageVersion = objRef.getPackageVersion(objRef.getClassName()); 20 | frameworkMapping.setVersion(packageVersion); 21 | frameworkMapping.setType(getHandlerName()); 22 | frameworkMapping.setContextPath(urlParse.getVirtualPath()); 23 | context.getPublish().Event(new StartEvent(EventType.FrameworkContextCount, objRef.getId(), getHandlerName().name(), 1)); 24 | try { 25 | analystsTargetObject(urlParse, objRef, frameworkMapping, context); 26 | context.getPublish().Event(new EndEvent(EventType.FrameworkContextCount, objRef.getId(),"framework完成分析")); 27 | } catch (Exception e) { 28 | context.getPublish().Error(new ErrorEvent(ErrorType.FrameworkError, objRef.getId(), e)); 29 | } 30 | context.pushFramework(frameworkMapping); 31 | } 32 | 33 | void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping frameworkRecord, Context context) throws Exception; 34 | 35 | HandlerType getHandlerName(); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/Jersey1Handler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.analysts.ListAnalysts; 5 | import router.analysts.SetAnalysts; 6 | import router.context.Context; 7 | import router.mapping.FrameworkMapping; 8 | import router.parse.UrlParse; 9 | import router.publish.*; 10 | import router.type.HandlerType; 11 | 12 | public class Jersey1Handler implements FrameworkHandler { 13 | @Override 14 | public void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping jersey1, Context context) throws Exception { 15 | SetAnalysts abstractRootResourcesRef = null; 16 | try { 17 | abstractRootResourcesRef = new SetAnalysts(objRef.getObjFields("webComponent", 18 | "application", "abstractRootResources")); 19 | } catch (Exception e) { 20 | throw new Exception("Jersey1上下文获取失败"); 21 | } 22 | context.getPublish().Event(new StartEvent(EventType.Jersey1FrameworkCount, 23 | abstractRootResourcesRef.getId(), getHandlerName().name(), abstractRootResourcesRef.size())); 24 | try { 25 | for (IAnalysts resourceRef : abstractRootResourcesRef) { 26 | String className = resourceRef.getObjFields("resourceClass", "name").convertToString(); 27 | String path = resourceRef.getObjFields("uriPath", "value").convertToString(); 28 | ListAnalysts subResourceMethodsRef = new ListAnalysts(resourceRef.getObjFields("subResourceMethods")); 29 | for (IAnalysts subResourceMethodRef : subResourceMethodsRef) { 30 | String subPath = subResourceMethodRef.getObjFields("uriPath", "value").convertToString(); 31 | String servletPath = UrlParse.concatSubPath(path, subPath); 32 | jersey1.recordServletMap(className, urlParse.getPathByMiddleware(servletPath)); 33 | } 34 | context.getPublish().Event( 35 | new EndEvent(EventType.Jersey1FrameworkAnalystsComplete, abstractRootResourcesRef.getId(), className)); 36 | } 37 | } catch (Exception e) { 38 | context.getPublish().Error(new ErrorEvent(ErrorType.Jersey1Error, abstractRootResourcesRef.getId(), e)); 39 | } 40 | } 41 | 42 | @Override 43 | public HandlerType getHandlerName() { 44 | return HandlerType.Jersey1; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/Jersey2Handler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.analysts.MapAnalysts; 5 | import router.analysts.SetAnalysts; 6 | import router.context.Context; 7 | import router.mapping.FrameworkMapping; 8 | import router.parse.UrlParse; 9 | import router.publish.*; 10 | import router.type.HandlerType; 11 | 12 | public class Jersey2Handler implements FrameworkHandler { 13 | @Override 14 | public void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping jersey2, Context context) throws Exception { 15 | SetAnalysts cachedClassesRef = null; 16 | try { 17 | cachedClassesRef = new SetAnalysts(objRef.getObjFields("webComponent", "appHandler", "application", "cachedClasses")); 18 | } catch (Exception e) { 19 | throw new Exception("Jersey2上下文获取失败"); 20 | } 21 | context.getPublish().Event(new StartEvent(EventType.Jersey2FrameworkCount, 22 | cachedClassesRef.getId(), getHandlerName().name(), cachedClassesRef.size())); 23 | try { 24 | for (IAnalysts classObjectRef : cachedClassesRef) { 25 | String className = classObjectRef.getStrFields("name"); 26 | MapAnalysts mapInstancesRef = new MapAnalysts(classObjectRef.getObjFields("annotationData", "annotations")); 27 | for (MapAnalysts.Entry mapInstanceRef : mapInstancesRef.getKV()) { 28 | String name = mapInstanceRef.getKey().getStrFields("name"); 29 | if (name.equals("javax.ws.rs.Path")) { 30 | MapAnalysts.Entry[] memberValuesRef = new MapAnalysts(mapInstanceRef.getValue().getObjFields("h", "memberValues")).getKV(); 31 | for (MapAnalysts.Entry memberValueRef : memberValuesRef) { 32 | if (memberValueRef.getKey().convertToString().equals("value")) { 33 | String path = memberValueRef.getValue().convertToString(); 34 | jersey2.recordServletMap(className, urlParse.getPathByMiddleware(path)); 35 | } 36 | } 37 | } 38 | } 39 | context.getPublish().Event(new EndEvent(EventType.Jersey2FrameworkAnalystsComplete, 40 | cachedClassesRef.getId(), className)); 41 | } 42 | } catch (Exception e) { 43 | context.getPublish().Error(new ErrorEvent(ErrorType.Jersey2Error, cachedClassesRef.getId(), e)); 44 | } 45 | } 46 | 47 | @Override 48 | public HandlerType getHandlerName() { 49 | return HandlerType.Jersey2; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/SpringMvcHandler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.*; 4 | import router.context.Context; 5 | import router.except.FieldExcept; 6 | import router.mapping.FrameworkMapping; 7 | import router.parse.UrlParse; 8 | import router.publish.*; 9 | import router.type.HandlerType; 10 | import router.utils.SpringUtils; 11 | 12 | public class SpringMvcHandler implements FrameworkHandler { 13 | @Override 14 | public void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping spring, Context context) throws Exception { 15 | ListAnalysts handlerMappingsRef = null; 16 | try { 17 | handlerMappingsRef = new ListAnalysts(objRef.getObjFields("handlerMappings")); 18 | } catch (Exception e) { 19 | throw new Exception("spring上下文获取失败"); 20 | } 21 | for (IAnalysts handlerMapperRef : handlerMappingsRef) { 22 | if (handlerMapperRef.getClassName().equals("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping")) { 23 | handlerRequestMapper(spring, handlerMapperRef, context); 24 | } else { 25 | handlerAbstractMap(spring, handlerMapperRef); 26 | } 27 | } 28 | } 29 | 30 | @Override 31 | public HandlerType getHandlerName() { 32 | return HandlerType.Spring; 33 | } 34 | 35 | private void handlerRequestMapper(FrameworkMapping spring, IAnalysts handlerMapperRef, Context context) throws Exception { 36 | MapAnalysts mapValueInstanceRef = null; 37 | try { 38 | mapValueInstanceRef = new MapAnalysts(handlerMapperRef.getObjFields("mappingRegistry", "registry")); 39 | } catch (FieldExcept e) { 40 | throw new Exception("registry对象获取失败"); 41 | } 42 | IAnalysts[] kvInstanceRef = mapValueInstanceRef.getValues(); 43 | context.getPublish().Event(new StartEvent( 44 | EventType.SpringFrameworkCount, mapValueInstanceRef.getId(), getHandlerName().name(), kvInstanceRef.length)); 45 | try { 46 | for (IAnalysts handlerRef : kvInstanceRef) { 47 | SetAnalysts patternsRef = SpringUtils.getPatternsRef(handlerRef); 48 | String className = handlerRef.getObjFields("handlerMethod", "beanType", "name").convertToString(); 49 | for (IAnalysts path : patternsRef) { 50 | spring.recordServletMap(className, path.convertToString()); 51 | } 52 | context.getPublish().Event(new EndEvent(EventType.SpringFrameworkAnalystsComplete, mapValueInstanceRef.getId(), className)); 53 | } 54 | } catch (Exception e) { 55 | context.getPublish().Error(new ErrorEvent(ErrorType.SpringError, mapValueInstanceRef.getId(), e)); 56 | } 57 | } 58 | 59 | private void handlerAbstractMap(FrameworkMapping spring, IAnalysts handlerMapperRef) { 60 | } 61 | } -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/Struts1Handler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.analysts.ListAnalysts; 5 | import router.analysts.MapAnalysts; 6 | import router.context.Context; 7 | import router.except.FieldExcept; 8 | import router.mapping.FrameworkMapping; 9 | import router.parse.UrlParse; 10 | import router.publish.*; 11 | import router.type.HandlerType; 12 | 13 | 14 | public class Struts1Handler implements FrameworkHandler { 15 | @Override 16 | public void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping struts1, Context context) throws Exception { 17 | try { 18 | IAnalysts refObj = objRef.getObjFields("actionConfigList"); 19 | handlerActionConfigList(refObj, struts1, urlParse, context); 20 | } catch (FieldExcept e) { 21 | throw new Exception("上下文获取失败"); 22 | } catch (NullPointerException e) { 23 | try { 24 | IAnalysts refObj = objRef.getObjFields("actionConfigs"); 25 | handlerActionConfigs(refObj, struts1, urlParse, context); 26 | } catch (FieldExcept e2) { 27 | throw new Exception("上下文获取失败"); 28 | } 29 | } 30 | } 31 | 32 | private void handlerActionConfigList(IAnalysts actionConfigListRef, FrameworkMapping struts1, UrlParse urlParse, Context context) { 33 | ListAnalysts list = new ListAnalysts(actionConfigListRef); 34 | context.getPublish().Event(new StartEvent(EventType.Struts1FrameworkCount, 35 | list.getId(), getHandlerName().name(), list.size())); 36 | try { 37 | for (IAnalysts actionRef : list) { 38 | recordHandler(urlParse, actionRef, struts1, list.getId(), context); 39 | } 40 | } catch (Exception e) { 41 | context.getPublish().Error(new ErrorEvent(ErrorType.Struts1Error, list.getId(), e)); 42 | } 43 | } 44 | 45 | private void handlerActionConfigs(IAnalysts actionConfigListRef, FrameworkMapping struts1, UrlParse urlParse, Context context) { 46 | MapAnalysts mapAnalysts = new MapAnalysts(actionConfigListRef); 47 | IAnalysts[] values = mapAnalysts.getValues(); 48 | context.getPublish().Event(new StartEvent(EventType.Struts1FrameworkCount, 49 | mapAnalysts.getId(), getHandlerName().name(), mapAnalysts.getValues().length)); 50 | try { 51 | for (IAnalysts actionRef : values) { 52 | recordHandler(urlParse, actionRef, struts1, mapAnalysts.getId(), context); 53 | } 54 | } catch (Exception e) { 55 | context.getPublish().Error(new ErrorEvent(ErrorType.Struts1Error, mapAnalysts.getId(), e)); 56 | } 57 | } 58 | 59 | public void recordHandler(UrlParse urlParse, IAnalysts objRef, FrameworkMapping struts1, long id, Context context) throws Exception { 60 | String path = null; 61 | try { 62 | path = urlParse.getPathByMiddleware(objRef.getStrFields("path")); 63 | } catch (Exception e) { 64 | throw new Exception("struts1 get path failed"); 65 | } 66 | String classname = null; 67 | try { 68 | classname = objRef.getStrFields("type"); 69 | } catch (Exception e) { 70 | context.getPublish().Event(new EndEvent(EventType.Struts1FrameworkAnalystsComplete, id, "maybe forward")); 71 | return; 72 | } 73 | struts1.recordServletMap(classname, path); 74 | context.getPublish().Event(new EndEvent(EventType.Struts1FrameworkAnalystsComplete, id, classname)); 75 | } 76 | 77 | @Override 78 | public HandlerType getHandlerName() { 79 | return HandlerType.Strut1; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/handler/Struts2Handler.java: -------------------------------------------------------------------------------- 1 | package router.handler; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.analysts.MapAnalysts; 5 | import router.context.Context; 6 | import router.except.FieldExcept; 7 | import router.mapping.FrameworkMapping; 8 | import router.parse.UrlParse; 9 | import router.publish.*; 10 | import router.type.HandlerType; 11 | 12 | public class Struts2Handler implements FrameworkHandler { 13 | @Override 14 | public void analystsTargetObject(UrlParse urlParse, IAnalysts objRef, FrameworkMapping strut2, Context context) throws Exception { 15 | if (objRef.isInstanceof("org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter") || 16 | objRef.isInstanceof("org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter")) { 17 | struts23(urlParse, objRef, strut2, context); 18 | } else if (objRef.isInstanceof("org.apache.struts2.dispatcher.FilterDispatcher")) { 19 | struts21(urlParse, objRef, strut2, context); 20 | } 21 | } 22 | 23 | @Override 24 | public HandlerType getHandlerName() { 25 | return HandlerType.Strut2; 26 | } 27 | 28 | private void struts21(UrlParse urlParse, IAnalysts objRef, FrameworkMapping strut2, Context context) throws Exception { 29 | IAnalysts packageContextsRef = null; 30 | try { 31 | packageContextsRef = objRef.getObjFields("dispatcher", 32 | "configurationManager", "configuration", "packageContexts"); 33 | } catch (FieldExcept e) { 34 | throw new Exception("package上下文获取失败"); 35 | } 36 | handlerPackageContexts(urlParse, packageContextsRef, strut2, context); 37 | } 38 | 39 | private void struts23(UrlParse urlParse, IAnalysts objRef, FrameworkMapping strut2, Context context) throws Exception { 40 | IAnalysts packageContextsRef = null; 41 | 42 | try { 43 | packageContextsRef = objRef.getObjFields("execute", 44 | "dispatcher", "configurationManager", "configuration", "packageContexts"); 45 | } catch (Exception e) { 46 | throw new Exception("package上下文获取失败"); 47 | } 48 | handlerPackageContexts(urlParse, packageContextsRef, strut2, context); 49 | } 50 | 51 | private void handlerPackageContexts(UrlParse urlParse, IAnalysts packageContextsRef, FrameworkMapping strut2, Context context) throws Exception { 52 | for (IAnalysts packageContextRef : new MapAnalysts(packageContextsRef).getValues()) { 53 | MapAnalysts actionConfigsRef = null; 54 | try { 55 | actionConfigsRef = new MapAnalysts(packageContextRef.getObjFields("actionConfigs")); 56 | } catch (FieldExcept e) { 57 | throw new Exception("action上下文获取失败"); 58 | } 59 | IAnalysts[] kvRef = actionConfigsRef.getValues(); 60 | context.getPublish().Event(new StartEvent(EventType.Struts2FrameworkCount, 61 | actionConfigsRef.getId(), getHandlerName().name(), kvRef.length)); 62 | try { 63 | String namespace = packageContextRef.getStrFields("namespace"); 64 | for (IAnalysts actionRef : kvRef) { 65 | String name = actionRef.getStrFields("name"); 66 | String className = actionRef.getStrFields("className"); 67 | String path = UrlParse.concatSubPath(namespace, name); 68 | strut2.recordServletMap(className, urlParse.getPathByMiddleware(path)); 69 | context.getPublish().Event(new EndEvent(EventType.Struts2FrameworkAnalystsComplete, 70 | actionConfigsRef.getId(), className)); 71 | } 72 | } catch (Exception e) { 73 | context.getPublish().Error(new ErrorEvent(ErrorType.Struts2Error, actionConfigsRef.getId(), e)); 74 | } 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/mapping/FilterMapping.java: -------------------------------------------------------------------------------- 1 | package router.mapping; 2 | 3 | public class FilterMapping { 4 | private Integer priority; 5 | private String className; 6 | private String urlPath; 7 | 8 | public FilterMapping(String className, String urlPath) { 9 | this.className = className; 10 | this.urlPath = urlPath; 11 | } 12 | 13 | public String getClassName() { 14 | return className; 15 | } 16 | 17 | public void setClassName(String className) { 18 | this.className = className; 19 | } 20 | 21 | public String getUrlPath() { 22 | return urlPath; 23 | } 24 | 25 | public void setUrlPath(String urlPath) { 26 | this.urlPath = urlPath; 27 | } 28 | 29 | public Integer getPriority() { 30 | return priority; 31 | } 32 | 33 | public void setPriority(Integer priority) { 34 | this.priority = priority; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/mapping/FrameworkMapping.java: -------------------------------------------------------------------------------- 1 | package router.mapping; 2 | 3 | import router.type.HandlerType; 4 | 5 | import java.util.*; 6 | 7 | public class FrameworkMapping { 8 | 9 | private HandlerType type; 10 | 11 | private String contextPath; 12 | 13 | private List urlMap; 14 | 15 | private String version; 16 | 17 | private HashMap __serlvetCache = new HashMap<>(); 18 | 19 | public FrameworkMapping() { 20 | urlMap = new ArrayList<>(); 21 | version = "UNKNOWN"; 22 | } 23 | 24 | 25 | public String getVersion() { 26 | return version; 27 | } 28 | 29 | public void setVersion(String version) { 30 | if (version != null) { 31 | this.version = version; 32 | } 33 | } 34 | 35 | public HandlerType getType() { 36 | return type; 37 | } 38 | 39 | public void setType(HandlerType type) { 40 | this.type = type; 41 | } 42 | 43 | public List getUrlMap() { 44 | return urlMap; 45 | } 46 | 47 | public void setUrlMap(List urlMap) { 48 | this.urlMap = urlMap; 49 | } 50 | 51 | public String getContextPath() { 52 | return contextPath; 53 | } 54 | 55 | public void setContextPath(String contextPath) { 56 | this.contextPath = contextPath; 57 | } 58 | 59 | public void recordServletMap(String classname, String url) { 60 | if (urlMap == null) urlMap = new ArrayList<>(); 61 | if (!__serlvetCache.containsKey(classname)) { 62 | ServletMapping servletMapping = new ServletMapping(classname, new ArrayList<>()); 63 | servletMapping.addPath(url); 64 | __serlvetCache.put(classname, servletMapping); 65 | urlMap.add(servletMapping); 66 | } else { 67 | __serlvetCache.get(classname).addPath(url); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/mapping/MiddlewareMapping.java: -------------------------------------------------------------------------------- 1 | package router.mapping; 2 | 3 | import router.type.MiddlewareType; 4 | 5 | import java.util.*; 6 | 7 | public class MiddlewareMapping { 8 | 9 | private MiddlewareType type; 10 | 11 | /** 12 | * virtual path 13 | * eg: http://127.0.0.1:8080/ 14 | *

15 | * virtual path is "/" 16 | */ 17 | private String virtualPath; 18 | 19 | /** 20 | * The real path of webroot in the operating system 21 | */ 22 | private String physicalPath; 23 | 24 | private String version; 25 | 26 | 27 | private List servletMap; 28 | 29 | 30 | private List filtersMap; 31 | 32 | private HashMap __serlvetCache = new HashMap<>(); 33 | private static Integer __filterPos = 0; 34 | 35 | public MiddlewareMapping() { 36 | version = "UNKNOWN"; 37 | servletMap = new ArrayList<>(); 38 | filtersMap = new ArrayList<>(); 39 | } 40 | 41 | 42 | public MiddlewareType getType() { 43 | return type; 44 | } 45 | 46 | public void setType(MiddlewareType type) { 47 | this.type = type; 48 | } 49 | 50 | public String getVirtualPath() { 51 | return virtualPath; 52 | } 53 | 54 | public void setVirtualPath(String virtualPath) { 55 | this.virtualPath = virtualPath; 56 | } 57 | 58 | public String getPhysicalPath() { 59 | return physicalPath; 60 | } 61 | 62 | public void setPhysicalPath(String physicalPath) { 63 | this.physicalPath = physicalPath; 64 | } 65 | 66 | public List getServletMap() { 67 | return servletMap; 68 | } 69 | 70 | public void coverAllServlet(List servletMap) { 71 | this.servletMap = servletMap; 72 | } 73 | 74 | public List getFilterMap() { 75 | return filtersMap; 76 | } 77 | 78 | public void recordFilterMap(FilterMapping filter) { 79 | if (filtersMap == null) filtersMap = new ArrayList(); 80 | filter.setPriority(__filterPos); 81 | __filterPos++; 82 | filtersMap.add(filter); 83 | } 84 | 85 | public void coverAllFilter(List filterMappings) { 86 | filtersMap = filterMappings; 87 | } 88 | 89 | 90 | public String getVersion() { 91 | return version; 92 | } 93 | 94 | public void setVersion(String version) { 95 | if (version != null) { 96 | this.version = version; 97 | } 98 | } 99 | 100 | 101 | public void recordServletMap(String classname, String url) { 102 | if (servletMap == null) servletMap = new ArrayList<>(); 103 | if (!__serlvetCache.containsKey(classname)) { 104 | ServletMapping servletMapping = new ServletMapping(classname, new ArrayList<>()); 105 | servletMapping.addPath(url); 106 | __serlvetCache.put(classname, servletMapping); 107 | servletMap.add(servletMapping); 108 | } else { 109 | __serlvetCache.get(classname).addPath(url); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/mapping/ServletMapping.java: -------------------------------------------------------------------------------- 1 | package router.mapping; 2 | 3 | import java.util.List; 4 | 5 | public class ServletMapping { 6 | public String classname; 7 | public List path; 8 | 9 | public ServletMapping(String name, List path) { 10 | this.classname = name; 11 | this.path = path; 12 | } 13 | 14 | public String getClassname() { 15 | return classname; 16 | } 17 | 18 | public void setClassname(String classname) { 19 | this.classname = classname; 20 | } 21 | 22 | public List getPath() { 23 | return path; 24 | } 25 | 26 | public void setPath(List path) { 27 | this.path = path; 28 | } 29 | 30 | public void addPath(String path) { 31 | if (!this.path.contains(path)) { 32 | this.path.add(path); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/middleware/JettyMiddleware.java: -------------------------------------------------------------------------------- 1 | package router.middleware; 2 | 3 | import router.analysts.ArrayAnalysts; 4 | import router.analysts.IAnalysts; 5 | import router.context.Context; 6 | import router.mapping.FilterMapping; 7 | import router.mapping.MiddlewareMapping; 8 | import router.except.MiddleWareError; 9 | import router.handler.BreakPointHandler; 10 | import router.parse.UrlParse; 11 | import router.pipeline.FilterPipeLine; 12 | import router.pipeline.ServletPipeLine; 13 | import router.publish.EndEvent; 14 | import router.publish.EventType; 15 | import router.publish.StartEvent; 16 | import router.type.MiddlewareType; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | public class JettyMiddleware implements BreakPointHandler { 22 | @Override 23 | public void handlerTarget(IAnalysts thisObject, Context context) throws MiddleWareError { 24 | try { 25 | MiddlewareMapping jetty = new MiddlewareMapping(); 26 | jetty.setType(MiddlewareType.Jetty); 27 | // set virtual path / root path 28 | setContextPath(jetty, thisObject); 29 | setVersion(thisObject, jetty); 30 | IAnalysts servletHandlerRef = thisObject.getObjFields("_servletHandler"); 31 | context.getPublish().Event(new StartEvent(EventType.MiddlewareContextCount, 32 | servletHandlerRef.getId(), getHandlerName().name(), 1)); 33 | 34 | setServletMapping(servletHandlerRef, jetty, context); 35 | setFilterMapping(servletHandlerRef, jetty, context); 36 | context.pushMiddleware(jetty); 37 | context.getPublish().Event( 38 | new EndEvent(EventType.MiddlewareContextAnalystsComplete, servletHandlerRef.getId(), "jetty完成分析")); 39 | } catch (Exception e) { 40 | throw MiddleWareError.JettyError(e.getMessage()); 41 | } 42 | } 43 | 44 | private void setVersion(IAnalysts thisObject, MiddlewareMapping jettyRecord) { 45 | String packageVersion = thisObject.getPackageVersion(thisObject.getClassName()); 46 | jettyRecord.setVersion(packageVersion); 47 | } 48 | 49 | private void setFilterMapping(IAnalysts servletHandlerRef, MiddlewareMapping jetty, Context context) throws Exception { 50 | ArrayAnalysts filterArrayRef = new ArrayAnalysts(servletHandlerRef.getObjFields("_filterMappings")); 51 | context.getPublish().Event(new StartEvent(EventType.FilterCount, filterArrayRef.getId(), filterArrayRef.getClassName(), filterArrayRef.size())); 52 | for (IAnalysts filterMapRef : filterArrayRef) { 53 | String className = filterMapRef.getObjFields("_holder", "_className").convertToString(); 54 | ArrayAnalysts pathsRef = new ArrayAnalysts(filterMapRef.getObjFields("_pathSpecs")); 55 | for (IAnalysts pathRef : pathsRef) { 56 | String path = pathRef.convertToString(); 57 | IAnalysts instance = filterMapRef.getObjFields("_holder", "_filter"); 58 | UrlParse urlParse = UrlParse.getMiddlewareParse(jetty.getVirtualPath(), path); 59 | FilterPipeLine.doFilter(urlParse, instance, context); 60 | jetty.recordFilterMap(new FilterMapping(className, UrlParse.concatSubPath(jetty.getVirtualPath(), path))); 61 | context.getPublish().Event(new EndEvent(EventType.FilterAnalystsComplete, filterArrayRef.getId(), className)); 62 | } 63 | } 64 | } 65 | 66 | private void setContextPath(MiddlewareMapping jettyRecord, IAnalysts thisObject) throws Exception { 67 | String path = thisObject.getStrFields("_contextPath"); 68 | jettyRecord.setVirtualPath(path); 69 | IAnalysts baseResourceRef = thisObject.getObjFields("_baseResource"); 70 | if (baseResourceRef.getClassName().equals("org.eclipse.jetty.util.resource.PathResource")) { 71 | String rootPath = baseResourceRef.getObjFields("path", "path").convertToString(); 72 | jettyRecord.setPhysicalPath(rootPath); 73 | } 74 | } 75 | 76 | private void setServletMapping(IAnalysts servletHandlerRef, MiddlewareMapping jetty, Context context) throws Exception { 77 | ArrayAnalysts servletsRef = new ArrayAnalysts(servletHandlerRef.getObjFields("_servlets")); 78 | HashMap servletMappings = getAliasHashMap(jetty, servletHandlerRef.getObjFields("_servletMappings")); 79 | context.getPublish().Event(new StartEvent(EventType.ServletCount, servletsRef.getId(), servletsRef.getClassName(), servletsRef.size())); 80 | for (IAnalysts servletHolderRef : servletsRef) { 81 | String alias = servletHolderRef.getStrFields("_name"); 82 | String className = servletHolderRef.getStrFields("_className"); 83 | IAnalysts servletWrapperRef = servletHolderRef.getObjFields("_servlet"); 84 | if (servletWrapperRef.isObjRef()) { 85 | ServletPipeLine.initServlet(MiddlewareType.Jetty, servletHolderRef, null); 86 | servletWrapperRef = servletHolderRef.getObjFields("_servlet"); 87 | } 88 | UrlParse[] urlParses = servletMappings.entrySet().stream().filter(elem -> elem.getValue().equals(alias)).map(Map.Entry::getKey).toArray(UrlParse[]::new); 89 | for (UrlParse urlParse : urlParses) { 90 | if (!servletWrapperRef.isObjRef()) { 91 | IAnalysts wrappedServletRef = servletWrapperRef.getObjFields("_wrappedServlet"); 92 | IAnalysts attributesRef = servletHandlerRef.getObjFields("_servletContext", "_map", "value"); 93 | ServletPipeLine.handlerServlet(urlParse, wrappedServletRef, attributesRef, context); 94 | } 95 | jetty.recordServletMap(className, urlParse.getPath()); 96 | context.getPublish().Event(new EndEvent(EventType.ServletAnalystsComplete, servletsRef.getId(), className)); 97 | } 98 | } 99 | } 100 | 101 | 102 | private HashMap getAliasHashMap(MiddlewareMapping middlewareMapping, IAnalysts servletMappingsRef) throws Exception { 103 | HashMap result = new HashMap<>(); 104 | ArrayAnalysts servletsMapRef = new ArrayAnalysts(servletMappingsRef); 105 | for (IAnalysts servletMapRef : servletsMapRef) { 106 | IAnalysts pathSpecsRef = servletMapRef.getObjFields("_pathSpecs"); 107 | String name = servletMapRef.getStrFields("_servletName"); 108 | ArrayAnalysts pathsRef = new ArrayAnalysts(pathSpecsRef); 109 | for (IAnalysts pathRef : pathsRef) { 110 | String path = pathRef.convertToString(); 111 | UrlParse urlRecord = UrlParse.getMiddlewareParse(middlewareMapping.getVirtualPath(), path); 112 | result.put(urlRecord, name); 113 | } 114 | } 115 | return result; 116 | } 117 | 118 | @Override 119 | public MiddlewareType getHandlerName() { 120 | return MiddlewareType.Jetty; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/parse/UrlParse.java: -------------------------------------------------------------------------------- 1 | package router.parse; 2 | 3 | 4 | import java.util.Objects; 5 | 6 | public class UrlParse { 7 | private UrlType urlType; 8 | private String virtualPath; 9 | private String basePath; 10 | public boolean frameworkMode; 11 | 12 | public UrlParse(UrlType urlType, String virtualPath, String basePath) { 13 | this.urlType = urlType; 14 | this.virtualPath = virtualPath; 15 | this.basePath = basePath; 16 | } 17 | 18 | public UrlType getUrlType() { 19 | return urlType; 20 | } 21 | 22 | public void setUrlType(UrlType urlType) { 23 | this.urlType = urlType; 24 | } 25 | 26 | public String getVirtualPath() { 27 | return virtualPath; 28 | } 29 | 30 | public void setVirtualPath(String virtualPath) { 31 | this.virtualPath = virtualPath; 32 | } 33 | 34 | public String getBasePath() { 35 | return basePath; 36 | } 37 | 38 | public void setBasePath(String basePath) { 39 | this.basePath = basePath; 40 | } 41 | 42 | public boolean isFrameworkMode() { 43 | return frameworkMode; 44 | } 45 | 46 | public void setFrameworkMode(boolean frameworkMode) { 47 | this.frameworkMode = frameworkMode; 48 | } 49 | 50 | public String getPath() { 51 | switch (urlType) { 52 | case EXACT: 53 | case WILD: 54 | return concatSubPath(virtualPath, "/", basePath ); 55 | case EXT: 56 | return concatSubPath(virtualPath, "/*" + basePath); 57 | default: 58 | return ""; 59 | } 60 | } 61 | 62 | public String getPathByMiddleware(String path){ 63 | if (virtualPath.equals("")) { 64 | virtualPath = "/"; 65 | } 66 | switch (getUrlType()) { 67 | case EXACT: 68 | return concatSubPath(getVirtualPath(), getBasePath()); 69 | case EXT: 70 | return concatSubPath(getVirtualPath(), path + "." + getBasePath()); 71 | case WILD: 72 | return concatSubPath(getVirtualPath(), getBasePath(), path); 73 | default: 74 | if (frameworkMode) { 75 | return concatSubPath("", path); 76 | } else { 77 | return ""; 78 | } 79 | } 80 | } 81 | 82 | public static String concatSubPath(String... paths) { 83 | StringBuffer result = new StringBuffer(); 84 | for (String path : paths) { 85 | result.append(path); 86 | } 87 | String goodPath = result.toString(); 88 | while (goodPath.contains("\\")) { 89 | goodPath = goodPath.replaceAll("\\\\", "/"); 90 | } 91 | while (goodPath.contains("//")) { 92 | goodPath = goodPath.replaceAll("//", "/"); 93 | } 94 | return goodPath; 95 | } 96 | 97 | public static UrlParse getMiddlewareParse(String virtualPath, String path){ 98 | if (path.contains("*")) { 99 | if (path.startsWith("*.")) { 100 | return new UrlParse(UrlType.EXT, virtualPath, path.substring(2)); 101 | } else { 102 | return new UrlParse(UrlType.WILD, virtualPath, path.substring(0, path.length() - 1)); 103 | } 104 | } else { 105 | return new UrlParse(UrlType.EXACT, virtualPath, path); 106 | } 107 | } 108 | 109 | 110 | @Override 111 | public boolean equals(Object o) { 112 | if (this == o) return true; 113 | if (o == null || getClass() != o.getClass()) return false; 114 | UrlParse urlRecord = (UrlParse) o; 115 | return Objects.equals(virtualPath, urlRecord.virtualPath) && Objects.equals(basePath, urlRecord.basePath); 116 | } 117 | 118 | @Override 119 | public int hashCode() { 120 | return Objects.hash(virtualPath, basePath); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/parse/UrlType.java: -------------------------------------------------------------------------------- 1 | package router.parse; 2 | 3 | public enum UrlType { 4 | DEFAULT, 5 | EXACT, 6 | WILD, 7 | EXT 8 | } -------------------------------------------------------------------------------- /server/core/src/main/java/router/pipeline/FilterPipeLine.java: -------------------------------------------------------------------------------- 1 | package router.pipeline; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.context.Context; 5 | import router.handler.Struts2Handler; 6 | import router.parse.UrlParse; 7 | 8 | public class FilterPipeLine { 9 | public static boolean doFilter(UrlParse urlParse, IAnalysts filterRef, Context context) { 10 | if (filterRef.isInstanceof("org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter") || 11 | filterRef.isInstanceof("org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter") || 12 | filterRef.isInstanceof("org.apache.struts2.dispatcher.FilterDispatcher")) { 13 | new Struts2Handler().handler(urlParse, filterRef, context); 14 | } 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/pipeline/ServletPipeLine.java: -------------------------------------------------------------------------------- 1 | package router.pipeline; 2 | 3 | import router.analysts.IAnalysts; 4 | import router.analysts.MapAnalysts; 5 | import router.context.Context; 6 | import router.handler.*; 7 | import router.parse.UrlParse; 8 | import router.type.MiddlewareType; 9 | 10 | public class ServletPipeLine { 11 | public static IAnalysts initServlet(MiddlewareType type, IAnalysts servletWrapperRef, IAnalysts classLoader) { 12 | switch (type) { 13 | case Tomcat: 14 | try { 15 | IAnalysts currentThreadClassLoader = servletWrapperRef.getCurrentThreadClassLoader(); 16 | servletWrapperRef.changeThreadClassLoader(classLoader); 17 | IAnalysts result = servletWrapperRef.invokeMethod("allocate"); 18 | servletWrapperRef.invokeMethod("unload"); 19 | servletWrapperRef.changeThreadClassLoader(currentThreadClassLoader); 20 | return result; 21 | }catch (Exception e){ 22 | return null; 23 | } 24 | case Jetty: 25 | try { 26 | // jetty9暂时不涉及上下文加载器的问题 27 | return servletWrapperRef.invokeMethod("initServlet"); 28 | }catch (Exception e){ 29 | return null; 30 | } 31 | default: 32 | return null; 33 | } 34 | } 35 | 36 | public static void handlerServlet(UrlParse urlParse, IAnalysts servletRef, IAnalysts attributeRef, Context context)throws Exception { 37 | if (servletRef.isInstanceof("org.apache.struts.action.ActionServlet")) { 38 | handlerStruts1(urlParse, attributeRef, context); 39 | } else if (servletRef.isInstanceof("org.springframework.web.servlet.DispatcherServlet")) { 40 | new SpringMvcHandler().handler(urlParse, servletRef, context); 41 | } else if (servletRef.isInstanceof("org.glassfish.jersey.servlet.ServletContainer")) { 42 | new Jersey2Handler().handler(urlParse, servletRef, context); 43 | } else if (servletRef.isInstanceof("com.sun.jersey.spi.container.servlet.ServletContainer")) { 44 | new Jersey1Handler().handler(urlParse, servletRef, context); 45 | } 46 | } 47 | 48 | public static void handlerStruts1(UrlParse urlParse, IAnalysts attributeRef, Context context) throws Exception { 49 | MapAnalysts.Entry[] mapInstanceRefs = new MapAnalysts(attributeRef).getKV(); 50 | for (MapAnalysts.Entry mapInstanceRef : mapInstanceRefs) { 51 | if (mapInstanceRef.getKey().convertToString().startsWith("org.apache.struts.action.MODULE")) { 52 | new Struts1Handler().handler(urlParse, mapInstanceRef.getValue(), context); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/EndEvent.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public class EndEvent implements Event { 4 | private EventType eventType; 5 | private Long uniqId; 6 | private String message; 7 | 8 | public EndEvent(EventType eventType, Long uniqId, String message) { 9 | this.eventType = eventType; 10 | this.message = message; 11 | this.uniqId = uniqId; 12 | } 13 | 14 | public String getMessage() { 15 | return message; 16 | } 17 | 18 | public void setMessage(String message) { 19 | this.message = message; 20 | } 21 | 22 | public Long getUniqId() { 23 | return uniqId; 24 | } 25 | 26 | public void setUniqId(Long uniqId) { 27 | this.uniqId = uniqId; 28 | } 29 | 30 | public EventType getEventType() { 31 | return eventType; 32 | } 33 | 34 | public void setEventType(EventType eventType) { 35 | this.eventType = eventType; 36 | } 37 | 38 | @Override 39 | public EventType getType() { 40 | return eventType; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/Error.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public interface Error { 4 | ErrorType getType(); 5 | } 6 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/ErrorEvent.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public class ErrorEvent implements Error{ 4 | private ErrorType errorType; 5 | private Long uniqId; 6 | private Exception exception; 7 | 8 | public ErrorEvent(ErrorType errorType, Long uniqId, Exception exception) { 9 | this.errorType = errorType; 10 | this.uniqId = uniqId; 11 | this.exception = exception; 12 | } 13 | 14 | public ErrorType getErrorType() { 15 | return errorType; 16 | } 17 | 18 | public void setErrorType(ErrorType errorType) { 19 | this.errorType = errorType; 20 | } 21 | 22 | public Long getUniqId() { 23 | return uniqId; 24 | } 25 | 26 | public void setUniqId(Long uniqId) { 27 | this.uniqId = uniqId; 28 | } 29 | 30 | public Exception getException() { 31 | return exception; 32 | } 33 | 34 | public void setException(Exception exception) { 35 | this.exception = exception; 36 | } 37 | 38 | @Override 39 | public ErrorType getType() { 40 | return errorType; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/ErrorType.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public enum ErrorType { 4 | BreakPointError, 5 | MiddlewareError, 6 | FilterError, 7 | ServletError, 8 | FrameworkError, 9 | Struts1Error, 10 | Struts2Error, 11 | SpringError, 12 | Jersey1Error, 13 | Jersey2Error, 14 | } 15 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/Event.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public interface Event { 4 | EventType getType(); 5 | } 6 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/EventType.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public enum EventType { 4 | BreakPointStart, 5 | BreakPointEnd, 6 | MiddlewareContextCount, 7 | MiddlewareContextAnalystsComplete, 8 | FilterCount, 9 | FilterAnalystsComplete, 10 | ServletCount, 11 | ServletAnalystsComplete, 12 | FrameworkContextCount, 13 | FrameworkContextAnalystsComplete, 14 | Jersey1FrameworkCount, 15 | Jersey1FrameworkAnalystsComplete, 16 | Jersey2FrameworkCount, 17 | Jersey2FrameworkAnalystsComplete, 18 | SpringFrameworkCount, 19 | SpringFrameworkAnalystsComplete, 20 | Struts1FrameworkCount, 21 | Struts1FrameworkAnalystsComplete, 22 | Struts2FrameworkCount, 23 | Struts2FrameworkAnalystsComplete, 24 | } 25 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/IPublish.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public interface IPublish { 4 | void Event(Event event); 5 | 6 | // 导致分析无法进行的错误 7 | void Error(Error event); 8 | } 9 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/StartEvent.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public class StartEvent implements Event { 4 | private EventType eventType; 5 | private Long uniqId; 6 | private String taskName; 7 | private Integer taskCount; 8 | 9 | public StartEvent(EventType eventType, Long uniqId, String taskName, Integer taskCount) { 10 | this.eventType = eventType; 11 | this.uniqId = uniqId; 12 | this.taskName = taskName; 13 | this.taskCount = taskCount; 14 | } 15 | 16 | public Long getUniqId() { 17 | return uniqId; 18 | } 19 | 20 | public void setUniqId(Long uniqId) { 21 | this.uniqId = uniqId; 22 | } 23 | 24 | public EventType getEventType() { 25 | return eventType; 26 | } 27 | 28 | public void setEventType(EventType eventType) { 29 | this.eventType = eventType; 30 | } 31 | 32 | public String getTaskName() { 33 | return taskName; 34 | } 35 | 36 | public void setTaskName(String taskName) { 37 | this.taskName = taskName; 38 | } 39 | 40 | public Integer getTaskCount() { 41 | return taskCount; 42 | } 43 | 44 | public void setTaskCount(Integer taskCount) { 45 | this.taskCount = taskCount; 46 | } 47 | 48 | @Override 49 | public EventType getType() { 50 | return eventType; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/publish/StdOutPublish.java: -------------------------------------------------------------------------------- 1 | package router.publish; 2 | 3 | public class StdOutPublish implements IPublish { 4 | public void Event(Event event) { 5 | System.out.println("Router Event[ " + event.toString() + " ]"); 6 | } 7 | 8 | public void Error(Error msg) { 9 | System.out.println("Router Error Event: " + msg.toString()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/type/HandlerType.java: -------------------------------------------------------------------------------- 1 | package router.type; 2 | 3 | public enum HandlerType { 4 | Spring, 5 | Jersey1, 6 | Jersey2, 7 | Strut1, 8 | Strut2 9 | } -------------------------------------------------------------------------------- /server/core/src/main/java/router/type/MiddlewareType.java: -------------------------------------------------------------------------------- 1 | package router.type; 2 | 3 | public enum MiddlewareType { 4 | Tomcat, 5 | Jetty 6 | } 7 | -------------------------------------------------------------------------------- /server/core/src/main/java/router/utils/SpringUtils.java: -------------------------------------------------------------------------------- 1 | package router.utils; 2 | 3 | import com.sun.jdi.ObjectReference; 4 | import com.sun.jdi.ThreadReference; 5 | import com.sun.jdi.Value; 6 | import router.analysts.IAnalysts; 7 | import router.analysts.InvokeUtils; 8 | import router.analysts.ObjAnalysts; 9 | import router.analysts.SetAnalysts; 10 | 11 | public class SpringUtils { 12 | /** 13 | * @param handlerRef 14 | * @return 15 | */ 16 | public static SetAnalysts getPatternsRef(IAnalysts handlerRef) throws Exception{ 17 | if (handlerRef.existFieldByName("mapping", "patternsCondition", "patterns")) { 18 | return new SetAnalysts(handlerRef.getObjFields("mapping", "patternsCondition", "patterns")); 19 | } else if (handlerRef.existFieldByName("mapping", "pathPatternsCondition", "patterns")) { 20 | return new SpringSetAnalysts(handlerRef.getObjFields("mapping", "pathPatternsCondition", "patterns")); 21 | } else { 22 | throw new Exception("No such handler"); 23 | } 24 | } 25 | 26 | public static class SpringSetAnalysts extends SetAnalysts { 27 | 28 | public SpringSetAnalysts(IAnalysts obj) { 29 | super(obj); 30 | init(obj.getRawValue()); 31 | if (isImplementOf("java.util.Set")) { 32 | return; 33 | } 34 | this.thread = obj.getThreadRawRef(); 35 | this.data = InvokeUtils.getSet(thread, (ObjectReference) getRawValue()) 36 | .stream() 37 | .map(elem -> new SpringPathPatternObj(ObjAnalysts.parseObject(thread, elem))) 38 | .toArray(ObjAnalysts[]::new); 39 | } 40 | } 41 | 42 | public static class SpringPathPatternObj extends ObjAnalysts { 43 | public SpringPathPatternObj(IAnalysts ref) { 44 | this.init(ref.getRawValue()); 45 | this.thread = ref.getThreadRawRef(); 46 | } 47 | 48 | @Override 49 | public String convertToString() { 50 | try { 51 | return getStrFields("patternString"); 52 | } catch (Exception e) { 53 | return null; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /server/core/src/test/java/Test.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | HashMap objectObjectHashMap = new HashMap<>(); 6 | objectObjectHashMap.put("test", "111"); 7 | Object[] array = objectObjectHashMap.keySet().toArray(); 8 | for(Object info : array){ 9 | System.out.println(objectObjectHashMap.get(info)); 10 | } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.7.12 9 | 10 | 11 | kd.router 12 | router 13 | 6.0 14 | pom 15 | router6 16 | debugger 17 | 18 | core 19 | server 20 | 21 | 22 | 11 23 | 11 24 | 11 25 | 26 | 27 | -------------------------------------------------------------------------------- /server/server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | kd.router 8 | router 9 | 6.0 10 | 11 | 12 | kd.router 13 | server 14 | 15 | 16 | 11 17 | 11 18 | UTF-8 19 | 20 | 21 | 22 | 23 | kd.router 24 | core 25 | 6.0 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | 33 | org.projectlombok 34 | lombok 35 | 36 | 37 | 38 | org.mybatis.spring.boot 39 | mybatis-spring-boot-starter 40 | 2.2.2 41 | 42 | 43 | 44 | org.xerial 45 | sqlite-jdbc 46 | 3.42.0.0 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-thymeleaf 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-websocket 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-starter-test 62 | test 63 | 64 | 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-maven-plugin 70 | 2.7.8 71 | 72 | true 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-compiler-plugin 78 | 3.8.1 79 | 80 | 81 | --add-exports=jdk.jdi/com.sun.tools.jdi=ALL-UNNAMED 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/RouterServerApplication.java: -------------------------------------------------------------------------------- 1 | package router.server; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import router.server.service.ConnectService; 12 | 13 | import javax.annotation.PreDestroy; 14 | 15 | @Slf4j 16 | @SpringBootApplication 17 | public class RouterServerApplication implements CommandLineRunner { 18 | @Value("${server.port}") 19 | private String port; 20 | @Autowired 21 | ConnectService service; 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(RouterServerApplication.class, args); 25 | } 26 | 27 | @Override 28 | public void run(String... args) throws Exception { 29 | } 30 | 31 | 32 | @PreDestroy 33 | public void onDestroy() throws Exception { 34 | service.closeConnect(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package router.server.config; 2 | 3 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.ArrayList; 8 | 9 | @Configuration 10 | public class CorsConfig{ 11 | @Bean(name = "corsFilter") 12 | public FilterRegistrationBean corsFilter() { 13 | FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 14 | registrationBean.setFilter(new CorsFilter()); 15 | ArrayList strings = new ArrayList<>(); 16 | strings.add("/*"); 17 | registrationBean.setUrlPatterns(strings); 18 | registrationBean.setOrder(1); 19 | return registrationBean; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/config/CorsFilter.java: -------------------------------------------------------------------------------- 1 | package router.server.config; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | 8 | public class CorsFilter implements Filter { 9 | @Override 10 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 11 | String orignalHeader = ((HttpServletRequest) servletRequest).getHeader("Origin"); 12 | if (orignalHeader != null) { 13 | ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Origin", orignalHeader); 14 | ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Credentials", "true"); 15 | ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); 16 | ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Headers", ((HttpServletRequest) servletRequest).getHeader("Access-Control-Request-Headers")); 17 | } 18 | filterChain.doFilter(servletRequest, servletResponse); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/config/DataBaseConfig.java: -------------------------------------------------------------------------------- 1 | package router.server.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.context.ServletContextAware; 6 | import router.server.mapper.*; 7 | 8 | import javax.servlet.ServletContext; 9 | 10 | 11 | @Component 12 | public class DataBaseConfig implements ServletContextAware { 13 | @Autowired 14 | FilterMapper filterMapper; 15 | @Autowired 16 | FrameworkMapper frameworkMapper; 17 | @Autowired 18 | HandlerMapper handlerMapper; 19 | @Autowired 20 | MiddlewareMapper middlewareMapper; 21 | @Autowired 22 | ProjectMapper projectMapper; 23 | @Autowired 24 | ServletMapper servletMapper; 25 | 26 | @Override 27 | public void setServletContext(ServletContext servletContext) { 28 | filterMapper.initTable(); 29 | frameworkMapper.initTable(); 30 | handlerMapper.initTable(); 31 | middlewareMapper.initTable(); 32 | projectMapper.initTable(); 33 | servletMapper.initTable(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/config/WebsocketConfig.java: -------------------------------------------------------------------------------- 1 | package router.server.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 6 | 7 | @Configuration 8 | public class WebsocketConfig { 9 | @Bean 10 | public ServerEndpointExporter serverEndpointExporter() { 11 | return new ServerEndpointExporter(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/context/DatabaseContext.java: -------------------------------------------------------------------------------- 1 | package router.server.context; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import router.analysts.IAnalysts; 6 | import router.context.Context; 7 | import router.mapping.FrameworkMapping; 8 | import router.mapping.MiddlewareMapping; 9 | import router.publish.IPublish; 10 | import router.server.entity.*; 11 | import router.server.mapper.*; 12 | import router.server.publish.WsPublish; 13 | import router.server.service.ProjectService; 14 | import router.type.HandlerType; 15 | import router.type.MiddlewareType; 16 | 17 | import java.util.Arrays; 18 | import java.util.HashMap; 19 | import java.util.List; 20 | import java.util.stream.Collectors; 21 | 22 | @Service 23 | public class DatabaseContext implements Context { 24 | 25 | @Autowired 26 | private ProjectService projectService; 27 | @Autowired 28 | MiddlewareMapper middlewareMapper; 29 | @Autowired 30 | ServletMapper servletMapper; 31 | @Autowired 32 | FilterMapper filterMapper; 33 | @Autowired 34 | FrameworkMapper frameworkMapper; 35 | @Autowired 36 | HandlerMapper handlerMapper; 37 | 38 | @Autowired 39 | WsPublish wsPublish; 40 | 41 | private HashMap analystsCache = new HashMap<>(); 42 | 43 | private boolean completeTask = false; 44 | 45 | public List getAllMiddleware(Integer projectId) { 46 | return middlewareMapper.selectTypeByProjectId(projectId); 47 | } 48 | 49 | public List getMiddlewarePanelByType(Integer projectId, MiddlewareType type) { 50 | return middlewareMapper.selectByProjectIdAndType(projectId, type.name()); 51 | } 52 | 53 | public List getSpecifiedFrameworkPanel(Integer projectId, HandlerType type) { 54 | return frameworkMapper.selectByProjectIdAndType(projectId, type.name()); 55 | } 56 | 57 | public List getFrameworkAllData(Integer id) { 58 | return frameworkMapper.selectTypeByProjectId(id); 59 | } 60 | 61 | public List getMiddlewareFilter(Integer middleId, Integer page, Integer limit) { 62 | return filterMapper.getFilterByMiddleId(middleId, page, limit); 63 | } 64 | 65 | public Integer getMiddlewareFilterCount(Integer middleId) { 66 | return filterMapper.selectFilterCountByMiddleId(middleId); 67 | } 68 | 69 | public List getMiddlewareServlet(Integer middleId, Integer page, Integer limit) { 70 | return servletMapper.getServletByMiddlewareId(middleId, page, limit); 71 | } 72 | 73 | public Integer getMiddlewareServletCount(Integer middleId) { 74 | return servletMapper.selectServletCountByMiddlewareId(middleId); 75 | } 76 | 77 | public List getFrameworkHandler(Integer frameworkId, Integer page, Integer limit) { 78 | return handlerMapper.selectAllByFrameworkId(frameworkId, page, limit); 79 | } 80 | 81 | public Integer getFrameworkHandlerCount(Integer frameworkId) { 82 | return handlerMapper.selectCountByFrameworkId(frameworkId); 83 | } 84 | 85 | @Override 86 | public void pushMiddleware(MiddlewareMapping middleware) { 87 | MiddlewareEntity middlewareEntity = new MiddlewareEntity(); 88 | middlewareEntity.setType(middleware.getType().toString()); 89 | middlewareEntity.setVersion(middleware.getVersion()); 90 | middlewareEntity.setVirtualPath(middleware.getVirtualPath()); 91 | middlewareEntity.setPhysicalPath(middleware.getPhysicalPath()); 92 | middlewareEntity.setProjectId(projectService.getCurrentProjectEntity().getId()); 93 | middlewareMapper.insert(middlewareEntity); 94 | List servlets = middleware.getServletMap().stream().map(e -> { 95 | ServletEntity servletEntity = new ServletEntity(); 96 | servletEntity.setClassname(e.getClassname()); 97 | servletEntity.setMiddleId(middlewareEntity.getId()); 98 | servletEntity.setUrls(e.getPath()); 99 | servletEntity.setMark(false); 100 | return servletEntity; 101 | }).collect(Collectors.toList()); 102 | if(!servlets.isEmpty()){ 103 | servletMapper.insertServlets(servlets); 104 | } 105 | List filters = middleware.getFilterMap().stream().map(f -> { 106 | FilterEntity filterEntity = new FilterEntity(); 107 | filterEntity.setUrl(f.getUrlPath()); 108 | filterEntity.setPriority(f.getPriority()); 109 | filterEntity.setClassname(f.getClassName()); 110 | filterEntity.setMark(false); 111 | filterEntity.setMiddleId(middlewareEntity.getId()); 112 | return filterEntity; 113 | }).collect(Collectors.toList()); 114 | if(!filters.isEmpty()){ 115 | filterMapper.insertFilters(filters); 116 | } 117 | } 118 | 119 | @Override 120 | public void pushFramework(FrameworkMapping framework) { 121 | FrameworkEntity frameworkEntity = new FrameworkEntity(); 122 | frameworkEntity.setProjectId(projectService.getCurrentProjectEntity().getId()); 123 | frameworkEntity.setVersion(framework.getVersion()); 124 | frameworkEntity.setType(framework.getType().toString()); 125 | frameworkEntity.setContextPath(framework.getContextPath()); 126 | try { 127 | frameworkMapper.insertFramework(frameworkEntity); 128 | }catch (Exception e){ 129 | e.printStackTrace(); 130 | } 131 | List urlMap = framework.getUrlMap().stream().map(e -> { 132 | HandlerEntity handlerEntity = new HandlerEntity(); 133 | handlerEntity.setFrameworkId(frameworkEntity.getId()); 134 | handlerEntity.setClassname(e.getClassname()); 135 | handlerEntity.setUrls(e.getPath()); 136 | handlerEntity.setMark(false); 137 | return handlerEntity; 138 | }).collect(Collectors.toList()); 139 | if(!urlMap.isEmpty()){ 140 | handlerMapper.insertHandler(urlMap); 141 | } 142 | } 143 | 144 | @Override 145 | public void completeTask() { 146 | projectService.completeProject(); 147 | } 148 | @Override 149 | public IPublish getPublish() { 150 | return wsPublish; 151 | } 152 | 153 | @Override 154 | public void pushAnalysts(IAnalysts analysts) { 155 | analystsCache.put(analysts.getId(), analysts); 156 | } 157 | 158 | @Override 159 | public IAnalysts getAnalystsByUniqId(Long id) { 160 | return analystsCache.remove(id); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/ApiResponse.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | public class ApiResponse { 10 | private Integer code; 11 | private Object msg; 12 | 13 | public static ApiResponse status200(Object msg) { 14 | return new ApiResponse(200, msg); 15 | } 16 | 17 | public static ApiResponse status400(Object msg) { 18 | return new ApiResponse(400, msg); 19 | } 20 | 21 | public static ApiResponse Ok() { 22 | return status200("Complete"); 23 | } 24 | 25 | public static ApiResponse Fail() { 26 | return status400("Fail"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/DataController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.*; 5 | import router.server.context.DatabaseContext; 6 | import router.server.mapper.FilterMapper; 7 | import router.server.mapper.HandlerMapper; 8 | import router.server.mapper.MiddlewareMapper; 9 | import router.server.mapper.ServletMapper; 10 | import router.server.service.ProjectService; 11 | import router.type.HandlerType; 12 | import router.type.MiddlewareType; 13 | 14 | /** 15 | * 数据获取类 16 | */ 17 | @RestController 18 | @RequestMapping("/data") 19 | public class DataController { 20 | 21 | @Autowired 22 | DatabaseContext context; 23 | 24 | @Autowired 25 | MiddlewareMapper middlewareMapper; 26 | 27 | @Autowired 28 | FilterMapper filterMapper; 29 | 30 | @Autowired 31 | ProjectService projectService; 32 | 33 | @Autowired 34 | ServletMapper servletMapper; 35 | @Autowired 36 | HandlerMapper handlerMapper; 37 | 38 | @GetMapping("/middleware/getall") 39 | public ApiResponse getAllMiddlewares() { 40 | return projectService.checkProject((p) -> 41 | ApiResponse.status200(context.getAllMiddleware(p.getId()))); 42 | } 43 | 44 | 45 | @GetMapping("/middleware/{target}/panel") 46 | public ApiResponse getSpecifiedMiddleware(@PathVariable("target") MiddlewareType type) { 47 | return projectService.checkProject(p -> 48 | ApiResponse.status200(context.getMiddlewarePanelByType(p.getId(), type))); 49 | } 50 | 51 | @GetMapping("/middleware/{middleid}/filter") 52 | public ApiResponse getSpecifiedMiddlewareFilter(@PathVariable("middleid") Integer middleid, @RequestParam("limit") Integer limit, 53 | @RequestParam("page") Integer page) { 54 | return projectService.checkProject(p -> 55 | ApiResponse.status200(context.getMiddlewareFilter(middleid, page, limit))); 56 | } 57 | 58 | @GetMapping("/middleware/{middleid}/filter/count") 59 | public ApiResponse getSpecifiedMiddlewareFilterCount(@PathVariable("middleid") Integer middleid) { 60 | return projectService.checkProject(p -> 61 | ApiResponse.status200(context.getMiddlewareFilterCount(middleid))); 62 | } 63 | 64 | @GetMapping("/middleware/{middleid}/urlmap") 65 | public ApiResponse getSpecifiedMiddlewareUrlMap(@PathVariable("middleid") Integer middleid, @RequestParam("limit") Integer limit, 66 | @RequestParam("page") Integer page) { 67 | return projectService.checkProject(p -> 68 | ApiResponse.status200(context.getMiddlewareServlet(middleid, page, limit))); 69 | } 70 | 71 | @GetMapping("/middleware/{middleid}/urlmap/count") 72 | public ApiResponse getSpecifiedMiddlewareUrlMapCount(@PathVariable("middleid") Integer middleid) { 73 | return projectService.checkProject(p -> 74 | ApiResponse.status200(context.getMiddlewareServletCount(middleid))); 75 | } 76 | 77 | @GetMapping("/framework/getall") 78 | public ApiResponse getAllFrameworks() { 79 | return projectService.checkProject((p) -> 80 | ApiResponse.status200(context.getFrameworkAllData(p.getId()))); 81 | } 82 | 83 | @GetMapping("/framework/{target}/panel") 84 | public ApiResponse getSpecifiedFrameworkPanel(@PathVariable("target") HandlerType type) { 85 | return projectService.checkProject(p -> 86 | ApiResponse.status200(context.getSpecifiedFrameworkPanel(p.getId(), type))); 87 | } 88 | 89 | @GetMapping("/framework/{frameworkid}/handlerMap") 90 | public ApiResponse getSpecifiedFrameworkHandlerMap(@PathVariable("frameworkid") Integer frameworkId, @RequestParam("limit") Integer limit, 91 | @RequestParam("page") Integer page) { 92 | return projectService.checkProject(p -> 93 | ApiResponse.status200(context.getFrameworkHandler(frameworkId, page, limit))); 94 | } 95 | 96 | @GetMapping("/framework/{frameworkid}/handlerMap/count") 97 | public ApiResponse getSpecifiedFrameworkHandlerMapCount(@PathVariable("frameworkid") Integer frameworkId) { 98 | return projectService.checkProject(p -> 99 | ApiResponse.status200(context.getFrameworkHandlerCount(frameworkId))); 100 | } 101 | 102 | @PostMapping("/middleware/mark") 103 | public ApiResponse markMiddleware(@RequestParam("id") Integer id, @RequestParam("flag") boolean flag) { 104 | return projectService.checkProject(p -> { 105 | servletMapper.mark(flag, id); 106 | return ApiResponse.Ok(); 107 | }); 108 | } 109 | 110 | @PostMapping("/framework/mark") 111 | public ApiResponse markFramework(@RequestParam("id") Integer id, @RequestParam("flag") boolean flag) { 112 | return projectService.checkProject(p -> { 113 | handlerMapper.mark(flag, id); 114 | return ApiResponse.Ok(); 115 | }); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | @Controller 7 | public class IndexController { 8 | @RequestMapping("/") 9 | public String index(){ 10 | return "index"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/LogController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RequestParam; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("/log") 9 | public class LogController { 10 | 11 | @RequestMapping("/get") 12 | public ApiResponse getLogData(@RequestParam("type") String type, @RequestParam("limit") Integer limit, @RequestParam("page") Integer page) { 13 | return ApiResponse.Ok(); 14 | } 15 | 16 | @RequestMapping("/clean") 17 | public ApiResponse clearLogData() { 18 | return ApiResponse.Ok(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/ManagerController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.*; 6 | import router.server.service.ConnectService; 7 | import router.server.service.ProjectService; 8 | 9 | @Slf4j 10 | @RestController 11 | @RequestMapping("/jdwp") 12 | public class ManagerController { 13 | 14 | @Autowired 15 | ProjectService projectService; 16 | 17 | @Autowired 18 | ConnectService connectService; 19 | 20 | @GetMapping("/testConnect") 21 | public ApiResponse connectTest() { 22 | return projectService.checkProject((p) -> 23 | connectService.testConnect(projectService.getCurrentProjectEntity())); 24 | } 25 | 26 | @PostMapping("/connect") 27 | public ApiResponse connectJVM() { 28 | return projectService.checkProject((p) -> 29 | connectService.connectJDWPWithProject(projectService.getCurrentProjectEntity())); 30 | } 31 | 32 | @DeleteMapping("/close") 33 | public ApiResponse deleteProject() { 34 | return projectService.checkProject((p) -> connectService.closeConnect()); 35 | } 36 | 37 | @GetMapping("/status") 38 | public ApiResponse getConnectStatus() { 39 | return projectService.checkProject(p -> connectService.statusConnect()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/ProgressController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import router.server.service.ProgressService; 8 | import router.server.service.ProjectService; 9 | 10 | /** 11 | * progress特定Task任务中的某个阶段性过程 12 | */ 13 | @RestController 14 | @RequestMapping("/progress") 15 | public class ProgressController { 16 | @Autowired 17 | ProjectService projectService; 18 | @Autowired 19 | ProgressService progressService; 20 | 21 | @GetMapping("/getall") 22 | public ApiResponse progressTaskList() { 23 | return projectService.checkProject(p -> 24 | ApiResponse.status200(progressService.getCurrentTasks())); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/ProjectCallback.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import router.server.entity.ProjectEntity; 4 | 5 | /** 6 | * 所有操作都必须在项目级下操作 7 | */ 8 | public interface ProjectCallback { 9 | ApiResponse callback(ProjectEntity project); 10 | } -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/ProjectController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | import org.springframework.web.bind.annotation.*; 4 | import router.server.entity.ProjectEntity; 5 | import router.server.service.ProjectService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | @RestController 9 | @RequestMapping("/project") 10 | public class ProjectController { 11 | @Autowired 12 | ProjectService projectService; 13 | 14 | @GetMapping("/get/all") 15 | public ApiResponse getAll() { 16 | return ApiResponse.status200(projectService.getAllProjects()); 17 | } 18 | 19 | @PostMapping("/creat") 20 | public ApiResponse create(@RequestBody ProjectEntity project) { 21 | if (projectService.getProjectByName(project.getAlias()) != null) { 22 | return ApiResponse.status400("项目已存在"); 23 | } else { 24 | projectService.createProject(project); 25 | return ApiResponse.status200("项目创建完成"); 26 | } 27 | } 28 | 29 | 30 | @PostMapping("/select/{id}") 31 | public ApiResponse selectProject(@PathVariable Integer id) { 32 | return projectService.selectProject(id) ? ApiResponse.Ok() : ApiResponse.Fail(); 33 | } 34 | 35 | @GetMapping("/current") 36 | public ApiResponse getCurrentProject() { 37 | ProjectEntity currentProjectEntity = projectService.getCurrentProjectEntity(); 38 | return currentProjectEntity != null ? ApiResponse.status200(currentProjectEntity) : ApiResponse.Fail(); 39 | } 40 | 41 | @PostMapping("/logout") 42 | public ApiResponse logout() { 43 | return projectService.logoutProject(); 44 | } 45 | 46 | @DeleteMapping("/delete/{id}") 47 | public ApiResponse deleteProject(@PathVariable Integer id) { 48 | projectService.deleteProject(id); 49 | return ApiResponse.Ok(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/controller/TaskController.java: -------------------------------------------------------------------------------- 1 | package router.server.controller; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.scheduling.config.Task; 6 | import org.springframework.web.bind.annotation.*; 7 | import router.server.service.ConnectService; 8 | import router.server.service.ProjectService; 9 | import router.server.service.TaskService; 10 | 11 | @RestController 12 | @RequestMapping("/task") 13 | public class TaskController { 14 | 15 | @Autowired 16 | private TaskService taskService; 17 | 18 | @Autowired 19 | private ConnectService connectService; 20 | 21 | @Autowired 22 | private ProjectService projectService; 23 | 24 | @GetMapping("/complete") 25 | public ApiResponse isComplete() { 26 | return projectService.checkProject(p -> { 27 | return projectService.getCurrentProjectEntity().isComplete() ? ApiResponse.Ok() : ApiResponse.Fail(); 28 | }); 29 | } 30 | 31 | @PostMapping("/start") 32 | public ApiResponse startTask() { 33 | return projectService.checkProject(p -> { 34 | if (connectService.getCurrentVirtualMachine() == null) { 35 | return ApiResponse.status400("你需要连接JDWP再启用调试任务"); 36 | } 37 | if (projectService.getCurrentProjectEntity().isComplete()) { 38 | return ApiResponse.status400("已经分析过一次了!"); 39 | } 40 | return taskService.startAnalysts(connectService.getCurrentVirtualMachine()); 41 | }); 42 | } 43 | 44 | @GetMapping("/status") 45 | public ApiResponse getStatus() { 46 | return projectService.checkProject(p -> taskService.statusAnalysts()); 47 | } 48 | 49 | @DeleteMapping("/stop") 50 | public ApiResponse stopTask() { 51 | return projectService.checkProject(p -> taskService.stopAnalysts()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/FilterEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class FilterEntity { 7 | private Integer id; 8 | private Integer priority; 9 | private Integer middleId; 10 | private String classname; 11 | private String url; 12 | private boolean mark; 13 | } 14 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/FrameworkEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class FrameworkEntity { 7 | private Integer id; 8 | private Integer projectId; 9 | private String type; 10 | private String contextPath; 11 | private String version; 12 | } 13 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/HandlerEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 与Servlet不同,Handler由各种web框架所产生(Spring/Strutx/JerseyX...) 9 | */ 10 | @Data 11 | public class HandlerEntity { 12 | private Integer id; 13 | private Integer frameworkId; 14 | private String classname; 15 | private List urls; 16 | private boolean mark; 17 | } 18 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/LogEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class LogEntity { 7 | private Integer Id; 8 | private Integer projectId; 9 | private String type; 10 | private String message; 11 | } 12 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/MiddlewareEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class MiddlewareEntity { 7 | private Integer id; 8 | private Integer projectId; 9 | private String type; 10 | private String virtualPath; 11 | private String physicalPath; 12 | private String version; 13 | } 14 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/ProjectEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | @Data 8 | public class ProjectEntity { 9 | private Integer id; 10 | private String alias; 11 | private String hostname; 12 | private String port; 13 | private Date createTime; 14 | private boolean complete; 15 | } 16 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/entity/ServletEntity.java: -------------------------------------------------------------------------------- 1 | package router.server.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | 8 | /** 9 | * 每一个Servlet绑定一个Middleware对象 10 | */ 11 | @Data 12 | public class ServletEntity { 13 | private Integer id; 14 | private Integer middleId; 15 | private String classname; 16 | private List urls; 17 | private boolean mark; 18 | } 19 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/handler/ListToStringHandler.java: -------------------------------------------------------------------------------- 1 | package router.server.handler; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.apache.ibatis.type.BaseTypeHandler; 6 | import org.apache.ibatis.type.JdbcType; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.sql.CallableStatement; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.List; 14 | 15 | @Component 16 | public class ListToStringHandler extends BaseTypeHandler { 17 | private static ObjectMapper mapper = new ObjectMapper(); 18 | 19 | @Override 20 | public void setNonNullParameter(PreparedStatement preparedStatement, int i, List list, JdbcType jdbcType) throws SQLException { 21 | try { 22 | preparedStatement.setString(i, mapper.writeValueAsString(list)); 23 | } catch (JsonProcessingException e) { 24 | throw new RuntimeException(e); 25 | } 26 | } 27 | 28 | @Override 29 | public List getNullableResult(ResultSet resultSet, String s) throws SQLException { 30 | String string = resultSet.getString(s); 31 | try { 32 | return mapper.readValue(string, List.class); 33 | } catch (JsonProcessingException e) { 34 | throw new RuntimeException(e); 35 | } 36 | } 37 | 38 | @Override 39 | public List getNullableResult(ResultSet resultSet, int i) throws SQLException { 40 | String string = resultSet.getString(i); 41 | try { 42 | return mapper.readValue(string, List.class); 43 | } catch (JsonProcessingException e) { 44 | throw new RuntimeException(e); 45 | } } 46 | 47 | @Override 48 | public List getNullableResult(CallableStatement callableStatement, int i) throws SQLException { 49 | String string = callableStatement.getString(i); 50 | try { 51 | return mapper.readValue(string, List.class); 52 | } catch (JsonProcessingException e) { 53 | throw new RuntimeException(e); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | public interface BaseMapper { 4 | void initTable(); 5 | } 6 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/FilterMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import router.server.entity.FilterEntity; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface FilterMapper extends BaseMapper{ 10 | int insertFilters(List filterEntities); 11 | List getFilterByMiddleId(Integer middleId, Integer page, Integer limit); 12 | Integer selectFilterCountByMiddleId(Integer middleId); 13 | 14 | void deleteByMiddlewareId(Integer middleId); 15 | } 16 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/FrameworkMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import router.server.entity.FrameworkEntity; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface FrameworkMapper extends BaseMapper{ 10 | List selectTypeByProjectId(Integer projectId); 11 | List selectByProjectId(Integer projectId); 12 | List selectByProjectIdAndType(Integer projectId, String type); 13 | int insertFramework(FrameworkEntity framework); 14 | } 15 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/HandlerMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import router.server.entity.HandlerEntity; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface HandlerMapper extends BaseMapper { 10 | void insertHandler(List handlerList); 11 | 12 | List selectAllByFrameworkId(Integer frameworkId, Integer page, Integer limit); 13 | 14 | int selectCountByFrameworkId(Integer frameworkId); 15 | 16 | void mark(boolean flag, Integer id); 17 | 18 | void deleteByFrameworkId(Integer frameworkId); 19 | } 20 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/MiddlewareMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import router.server.entity.MiddlewareEntity; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface MiddlewareMapper extends BaseMapper { 10 | List selectTypeByProjectId(Integer projectId, String... types); 11 | 12 | List selectByProjectIdAndType(Integer projectId, String type); 13 | 14 | List selectByProjectId(Integer projectId); 15 | int insert(MiddlewareEntity middlewareEntity); 16 | 17 | void deleteMiddlewareByProjectId(Integer id); 18 | } 19 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/ProjectMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import router.server.entity.ProjectEntity; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface ProjectMapper extends BaseMapper { 10 | List getAllProjectList(); 11 | ProjectEntity getProjectByName(String alias); 12 | ProjectEntity getProjectById(Integer id); 13 | void deleteProjectById(Integer id); 14 | void saveProject(ProjectEntity project); 15 | void completeProject(boolean complete, Integer id); 16 | } 17 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/mapper/ServletMapper.java: -------------------------------------------------------------------------------- 1 | package router.server.mapper; 2 | 3 | import router.server.entity.ServletEntity; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface ServletMapper extends BaseMapper{ 10 | int insertServlets(List servletEntityList); 11 | List getAllServlet(); 12 | List getServletByMiddlewareId(Integer middleId, Integer page, Integer limit); 13 | Integer selectServletCountByMiddlewareId(Integer middleId); 14 | void mark(boolean flag, Integer id); 15 | 16 | void deleteByMiddlewareId(Integer middleId); 17 | } 18 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/publish/ProgressTask.java: -------------------------------------------------------------------------------- 1 | package router.server.publish; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 分析进程中的某个阶段性任务 7 | */ 8 | @Data 9 | public class ProgressTask { 10 | // 远程集合对象的ID 11 | private Long Id; 12 | private String taskName; 13 | // 阶段性任务的总量 14 | private Integer count; 15 | // 阶段性任务的完成总量 16 | private Integer current; 17 | private String message; 18 | private String error; 19 | private boolean fail; 20 | public void updateCount(){ 21 | current++; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/publish/ServerEncoder.java: -------------------------------------------------------------------------------- 1 | package router.server.publish; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.json.JsonMapper; 5 | 6 | import javax.websocket.EncodeException; 7 | import javax.websocket.Encoder; 8 | import javax.websocket.EndpointConfig; 9 | 10 | /** 11 | * Json编码器 12 | */ 13 | public class ServerEncoder implements Encoder.Text { 14 | private static final JsonMapper jsonMapper = new JsonMapper(); 15 | 16 | @Override 17 | public void destroy() { 18 | } 19 | 20 | @Override 21 | public void init(EndpointConfig arg0) { 22 | } 23 | @Override 24 | public String encode(ProgressTask result) throws EncodeException { 25 | try { 26 | return jsonMapper.writeValueAsString(result); 27 | } catch (JsonProcessingException e) { 28 | throw new RuntimeException(e); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/publish/WsPublish.java: -------------------------------------------------------------------------------- 1 | package router.server.publish; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import router.publish.*; 6 | import router.publish.Error; 7 | import router.server.service.ProgressService; 8 | 9 | import javax.websocket.EncodeException; 10 | import javax.websocket.OnClose; 11 | import javax.websocket.OnOpen; 12 | import javax.websocket.Session; 13 | import javax.websocket.server.ServerEndpoint; 14 | import java.io.IOException; 15 | import java.util.HashSet; 16 | import java.util.Objects; 17 | import java.util.concurrent.ExecutorService; 18 | import java.util.concurrent.Executors; 19 | 20 | @Component 21 | @ServerEndpoint(value = "/ws/event", encoders = {ServerEncoder.class}) 22 | public class WsPublish implements IPublish { 23 | @Autowired 24 | ProgressService progressService; 25 | 26 | private static final HashSet sessionMap = new HashSet<>(); 27 | protected ExecutorService executorService = Executors.newFixedThreadPool(10); 28 | 29 | @OnOpen 30 | public void onOpen(Session session) { 31 | sessionMap.add(session); 32 | } 33 | 34 | @OnClose 35 | public void close(Session session) { 36 | sessionMap.remove(session); 37 | } 38 | 39 | public void sendObject(Object obj) { 40 | for (Session session : sessionMap) { 41 | if (session.isOpen()) { 42 | synchronized (session) { 43 | try { 44 | session.getBasicRemote().sendObject(obj); 45 | } catch (IOException | EncodeException e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | } 50 | } 51 | 52 | } 53 | 54 | @Override 55 | public void Event(Event event) { 56 | executorService.execute(() -> { 57 | ProgressTask result = null; 58 | switch (event.getType()) { 59 | case BreakPointStart: 60 | case MiddlewareContextCount: 61 | case FilterCount: 62 | case ServletCount: 63 | case Jersey1FrameworkCount: 64 | case Jersey2FrameworkCount: 65 | case SpringFrameworkCount: 66 | case Struts1FrameworkCount: 67 | case Struts2FrameworkCount: 68 | result = progressService.registryTask((StartEvent) event); 69 | break; 70 | case MiddlewareContextAnalystsComplete: 71 | case FilterAnalystsComplete: 72 | case ServletAnalystsComplete: 73 | case Jersey1FrameworkAnalystsComplete: 74 | case Jersey2FrameworkAnalystsComplete: 75 | case SpringFrameworkAnalystsComplete: 76 | case Struts1FrameworkAnalystsComplete: 77 | case Struts2FrameworkAnalystsComplete: 78 | case BreakPointEnd: 79 | result = progressService.updateTask((EndEvent) event); 80 | break; 81 | } 82 | if (result == null) { 83 | return; 84 | } 85 | sendObject(result); 86 | }); 87 | } 88 | 89 | @Override 90 | public void Error(Error error) { 91 | executorService.execute(() -> { 92 | ((ErrorEvent)error).getException().printStackTrace(); 93 | ProgressTask progressTask = progressService.handlerErrorTask((ErrorEvent) error); 94 | sendObject(progressTask); 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/service/ConnectService.java: -------------------------------------------------------------------------------- 1 | package router.server.service; 2 | 3 | import com.sun.jdi.VirtualMachine; 4 | import com.sun.jdi.connect.Connector; 5 | import com.sun.jdi.connect.IllegalConnectorArgumentsException; 6 | import com.sun.tools.jdi.SocketAttachingConnector; 7 | import lombok.Getter; 8 | import org.springframework.stereotype.Service; 9 | import router.server.controller.ApiResponse; 10 | import router.server.entity.ProjectEntity; 11 | 12 | import java.io.IOException; 13 | import java.util.Map; 14 | 15 | @Getter 16 | @Service 17 | public class ConnectService { 18 | 19 | private VirtualMachine currentVirtualMachine; 20 | 21 | public ApiResponse testConnect(ProjectEntity projectEntity) { 22 | try { 23 | VirtualMachine virtualMachine = connectJDWP(projectEntity.getHostname(), projectEntity.getPort()); 24 | if (virtualMachine != null) { 25 | closeJDWP(virtualMachine); 26 | return ApiResponse.Ok(); 27 | } 28 | return ApiResponse.status400("远程对象为空,可能需要重启目标服务"); 29 | } catch (Exception e) { 30 | return ApiResponse.status400(e.getMessage()); 31 | } 32 | } 33 | 34 | public VirtualMachine connectJDWP(String hostname, String port) throws IllegalConnectorArgumentsException, IOException { 35 | SocketAttachingConnector connector = new SocketAttachingConnector(); 36 | Map argMap = connector.defaultArguments(); 37 | argMap.get("hostname").setValue(hostname); 38 | argMap.get("port").setValue(port); 39 | argMap.get("timeout").setValue("3000"); 40 | return connector.attach(argMap); 41 | } 42 | 43 | /** 44 | * 每一个调试连接的关闭操作: 45 | * 1.取消所有断点 46 | * 2.无论是否挂起都要进行恢复操作,防止JVM永久性挂起 47 | * 3.关闭socket层面的连接 48 | */ 49 | public static void closeJDWP(VirtualMachine vm) { 50 | if (vm != null) { 51 | vm.eventRequestManager().deleteAllBreakpoints(); 52 | vm.resume(); 53 | vm.dispose(); 54 | } 55 | } 56 | 57 | public ApiResponse connectJDWPWithProject(ProjectEntity projectEntity) { 58 | try { 59 | VirtualMachine virtualMachine = connectJDWP(projectEntity.getHostname(), projectEntity.getPort()); 60 | if (virtualMachine != null) { 61 | currentVirtualMachine = virtualMachine; 62 | return ApiResponse.Ok(); 63 | } else { 64 | return ApiResponse.status400("远程对象为空,可能需要重启目标服务"); 65 | } 66 | } catch (Exception e) { 67 | return ApiResponse.status400(e.getMessage()); 68 | } 69 | } 70 | 71 | public ApiResponse closeConnect() { 72 | closeJDWP(currentVirtualMachine); 73 | currentVirtualMachine = null; 74 | return ApiResponse.Ok(); 75 | } 76 | 77 | public ApiResponse statusConnect() { 78 | return currentVirtualMachine != null ? ApiResponse.status200("连接已建立") : ApiResponse.status400("未建立连接"); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/service/ProgressService.java: -------------------------------------------------------------------------------- 1 | package router.server.service; 2 | 3 | import lombok.Getter; 4 | import org.springframework.stereotype.Service; 5 | import router.publish.EndEvent; 6 | import router.publish.ErrorEvent; 7 | import router.publish.StartEvent; 8 | import router.server.publish.ProgressTask; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Optional; 13 | 14 | @Service 15 | @Getter 16 | public class ProgressService { 17 | List currentTasks = new ArrayList<>(); 18 | 19 | public ProgressTask registryTask(StartEvent eventPackage) { 20 | if (eventPackage.getTaskCount() == 0) { 21 | return null; 22 | } 23 | ProgressTask progressTask = new ProgressTask(); 24 | progressTask.setId(eventPackage.getUniqId()); 25 | progressTask.setTaskName(eventPackage.getTaskName()); 26 | progressTask.setCount(eventPackage.getTaskCount()); 27 | progressTask.setCurrent(0); 28 | progressTask.setMessage(""); 29 | currentTasks.add(progressTask); 30 | return progressTask; 31 | } 32 | 33 | public ProgressTask updateTask(EndEvent eventPackage) { 34 | Optional first = currentTasks.stream().filter(task -> task.getId().equals(eventPackage.getUniqId())).findFirst(); 35 | if (first.isPresent()) { 36 | ProgressTask progressTask = first.get(); 37 | progressTask.updateCount(); 38 | progressTask.setMessage(eventPackage.getMessage()); 39 | return progressTask; 40 | } 41 | throw new RuntimeException("No progress task found for event type: " + eventPackage.getType().name()); 42 | } 43 | 44 | public ProgressTask handlerErrorTask(ErrorEvent errorEvent) { 45 | Optional first = currentTasks.stream().filter(task -> task.getId().equals(errorEvent.getUniqId())).findFirst(); 46 | if (first.isPresent()) { 47 | ProgressTask progressTask = first.get(); 48 | progressTask.setFail(true); 49 | System.out.println(errorEvent.getType().name()); 50 | System.out.printf(errorEvent.getErrorType().name()); 51 | errorEvent.getException().printStackTrace(); 52 | progressTask.setError(errorEvent.getException().getMessage()); 53 | return progressTask; 54 | } 55 | throw new RuntimeException("No progress task found for event type: " + errorEvent.getType().name()); 56 | } 57 | 58 | public void clearProgress() { 59 | currentTasks.clear(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/service/ProjectService.java: -------------------------------------------------------------------------------- 1 | package router.server.service; 2 | 3 | import lombok.Getter; 4 | import router.server.controller.ProjectCallback; 5 | import router.server.controller.ApiResponse; 6 | import router.server.entity.FrameworkEntity; 7 | import router.server.entity.MiddlewareEntity; 8 | import router.server.entity.ProjectEntity; 9 | import router.server.mapper.*; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | @Service 16 | public class ProjectService { 17 | @Autowired 18 | ProjectMapper projectMapper; 19 | 20 | @Autowired 21 | MiddlewareMapper middlewareMapper; 22 | @Autowired 23 | FilterMapper filterMapper; 24 | 25 | @Autowired 26 | ServletMapper servletMapper; 27 | 28 | @Autowired 29 | FrameworkMapper frameworkMapper; 30 | 31 | @Autowired 32 | HandlerMapper handlerMapper; 33 | 34 | @Getter 35 | ProjectEntity currentProjectEntity = null; 36 | 37 | public List getAllProjects() { 38 | return projectMapper.getAllProjectList(); 39 | } 40 | 41 | public void createProject(ProjectEntity projectEntity) { 42 | projectMapper.saveProject(projectEntity); 43 | currentProjectEntity = projectEntity; 44 | } 45 | 46 | public ProjectEntity getProjectByName(String name) { 47 | return projectMapper.getProjectByName(name); 48 | } 49 | 50 | public void completeProject() { 51 | currentProjectEntity.setComplete(true); 52 | projectMapper.completeProject(true, currentProjectEntity.getId()); 53 | } 54 | 55 | 56 | public boolean selectProject(Integer id) { 57 | ProjectEntity project = projectMapper.getProjectById(id); 58 | if (project == null) { 59 | return false; 60 | } 61 | currentProjectEntity = project; 62 | return true; 63 | } 64 | 65 | public void deleteProject(Integer id) { 66 | projectMapper.deleteProjectById(id); 67 | List middlewareEntities = middlewareMapper.selectByProjectId(id); 68 | middlewareMapper.deleteMiddlewareByProjectId(id); 69 | for (MiddlewareEntity middlewareEntity : middlewareEntities) { 70 | filterMapper.deleteByMiddlewareId(middlewareEntity.getId()); 71 | servletMapper.deleteByMiddlewareId(middlewareEntity.getId()); 72 | } 73 | List frameworkEntities = frameworkMapper.selectByProjectId(id); 74 | for (FrameworkEntity frameworkEntity : frameworkEntities) { 75 | handlerMapper.deleteByFrameworkId(frameworkEntity.getId()); 76 | } 77 | } 78 | 79 | public ApiResponse checkProject(ProjectCallback callback) { 80 | if (currentProjectEntity == null) { 81 | return ApiResponse.status400("还未选择指定项目"); 82 | } 83 | return callback.callback(currentProjectEntity); 84 | } 85 | 86 | public ApiResponse logoutProject() { 87 | currentProjectEntity = null; 88 | return ApiResponse.Ok(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /server/server/src/main/java/router/server/service/TaskService.java: -------------------------------------------------------------------------------- 1 | package router.server.service; 2 | 3 | import com.sun.jdi.VirtualMachine; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import router.DebugCore; 7 | import router.middleware.JettyMiddleware; 8 | import router.middleware.TomcatMiddleware; 9 | import router.server.context.DatabaseContext; 10 | import router.server.controller.ApiResponse; 11 | 12 | @Service 13 | public class TaskService { 14 | DebugCore debugThread; 15 | @Autowired 16 | ConnectService connectService; 17 | @Autowired 18 | DatabaseContext databaseContext; 19 | @Autowired 20 | ProgressService progressService; 21 | 22 | 23 | public ApiResponse startAnalysts(VirtualMachine vm) { 24 | if (debugThread != null) { 25 | return ApiResponse.status400("已存在分析线程"); 26 | } 27 | debugThread = DebugCore.build(vm, databaseContext); 28 | debugThread.registryHandler("org.apache.catalina.mapper.Mapper", 29 | "internalMap", new TomcatMiddleware()); 30 | debugThread.registryHandler("org.eclipse.jetty.servlet.ServletContextHandler", 31 | "doScope", new JettyMiddleware()); 32 | new Thread(debugThread).start(); 33 | return ApiResponse.status200("分析线程启动"); 34 | } 35 | 36 | public ApiResponse stopAnalysts() { 37 | if (debugThread != null) { 38 | debugThread.stopTask(); 39 | debugThread = null; 40 | } 41 | progressService.clearProgress(); 42 | return ApiResponse.Ok(); 43 | } 44 | 45 | public ApiResponse statusAnalysts() { 46 | return debugThread != null ? ApiResponse.status200("已存在任务") : ApiResponse.status400("无任务"); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /server/server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9090 2 | spring.mvc.view.prefix=classpath:/templates/ 3 | spring.mvc.view.suffix=.html 4 | spring.mvc.static-path-pattern=/** 5 | spring.datasource.url=jdbc:sqlite:route.db 6 | spring.datasource.driver-class-name=org.sqlite.JDBC 7 | #mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 8 | mybatis.mapper-locations=classpath:mapper/*.xml -------------------------------------------------------------------------------- /server/server/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | .______ ______ __ __ .___________. _______ .______ 3 | | _ \ / __ \ | | | | | || ____|| _ \ 4 | | |_) | | | | | | | | | `---| |----`| |__ | |_) | 5 | | / | | | | | | | | | | | __| | / 6 | | |\ \----.| `--' | | `--' | | | | |____ | |\ \----. 7 | | _| `._____| \______/ \______/ |__| |_______|| _| `._____| 8 | 9 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/FilterMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | CREATE TABLE IF NOT EXISTS `filter` 16 | ( 17 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 18 | `middleId` TEXT NOT NULL, 19 | `priority` INT NOT NULL, 20 | `classname` TEXT NOT NULL, 21 | `url` TEXT NOT NULL, 22 | `mark` TEXT 23 | ); 24 | 25 | 26 | 27 | insert into filter(id, middleId,priority,classname,url,mark) 28 | VALUES 29 | 30 | (#{item.id},#{item.middleId},#{item.priority},#{item.classname},#{item.url},#{item.mark}) 31 | 32 | 33 | 34 | 37 | 38 | 42 | 43 | delete from filter where middleId = #{middleId} 44 | 45 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/FrameworkMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CREATE TABLE IF NOT EXISTS `framework` 9 | ( 10 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 11 | `projectId` INT NOT NULL, 12 | `type` TEXT NOT NULL, 13 | `contextPath` TEXT NOT NULL, 14 | `version` TEXT 15 | ); 16 | 17 | 18 | 19 | INSERT INTO framework (id, projectId, type, contextPath, version) 20 | VALUES (#{id}, #{projectId}, #{type}, #{contextPath}, #{version}) 21 | 22 | 23 | 26 | 27 | 30 | 33 | 34 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/HandlerMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | CREATE TABLE IF NOT EXISTS `handler` 15 | ( 16 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 17 | `frameworkId` INT NOT NULL, 18 | `classname` TEXT NOT NULL, 19 | `urls` TEXT NOT NULL, 20 | `mark` TEXT 21 | ); 22 | 23 | 24 | 25 | insert into handler(id, frameworkId,classname,urls,mark) 26 | VALUES 27 | 28 | (#{item.id},#{item.frameworkId},#{item.classname},#{item.urls,jdbcType=VARCHAR, typeHandler=router.server.handler.ListToStringHandler},#{item.mark}) 29 | 30 | 31 | 32 | 35 | 36 | 39 | 40 | update handler 41 | set mark=#{flag} 42 | where id =#{id} 43 | 44 | 45 | delete 46 | from handler 47 | where frameworkId = #{frameworkId} 48 | 49 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/MiddlewareMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CREATE TABLE IF NOT EXISTS `middleware` 9 | ( 10 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 11 | `projectId` INTEGER NOT NULL, 12 | `type` TEXT NOT NULL, 13 | `virtualPath` TEXT NOT NULL, 14 | `physicalPath` TEXT NOT NULL, 15 | `version` TEXT 16 | ); 17 | 18 | 19 | 21 | INSERT INTO middleware (id, projectId, type, virtualPath, physicalPath, version) 22 | VALUES (#{id}, #{projectId}, #{type}, #{virtualPath}, #{physicalPath}, #{version}) 23 | 24 | 28 | 29 | 32 | 33 | 36 | 37 | 38 | delete from middleware where projectId = #{projectId} 39 | 40 | 41 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/ProjectMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 34 | 38 | 43 | 44 | 49 | 50 | 52 | INSERT INTO project(id, alias, hostname, port, complete, createTime) 53 | VALUES (#{id}, #{alias}, #{hostname}, #{port}, #{complete}, #{createTime}) 54 | 55 | 56 | DELETE 57 | from project 58 | WHERE id = #{id} 59 | 60 | 61 | 62 | UPDATE project set complete=#{complete} where id=#{id} 63 | 64 | -------------------------------------------------------------------------------- /server/server/src/main/resources/mapper/ServletMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | CREATE TABLE IF NOT EXISTS `servlet` 16 | ( 17 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 18 | `classname` TEXT NOT NULL, 19 | `middleId` INT NOT NULL, 20 | `urls` TEXT NOT NULL, 21 | `mark` TEXT 22 | ); 23 | 24 | 25 | insert into servlet(id, middleId,classname,urls,mark) 26 | VALUES 27 | 28 | (#{item.id},#{item.middleId},#{item.classname},#{item.urls,jdbcType=VARCHAR, typeHandler=router.server.handler.ListToStringHandler},#{item.mark}) 29 | 30 | 31 | 32 | 35 | 38 | 39 | 42 | 43 | 44 | update servlet 45 | set mark = #{flag} 46 | where id = #{id} 47 | 48 | 49 | delete from servlet where middleId = #{middleId} 50 | 51 | -------------------------------------------------------------------------------- /server/server/src/main/resources/static/css/app.16e5396e.css: -------------------------------------------------------------------------------- 1 | .project-name-icon[data-v-693e291a]{margin-left:10px;display:inline-block;color:#4b4b52;font-size:18px}.projectSelect[data-v-693e291a]{color:#6b89cb}.project-title[data-v-e4de1dfe]{padding:0;display:flex;justify-content:space-between;margin-bottom:10px}.float-div[data-v-e4de1dfe],.project-title-name[data-v-e4de1dfe]{font-size:24px;font-weight:700}.float-div[data-v-e4de1dfe]{display:inline-block}.project-bottom-button[data-v-6b741e2d]{width:800px}.box-left[data-v-6b741e2d]{float:left}.box-right[data-v-6b741e2d]{float:right}.main[data-v-033cb069]{background-color:#fff;border-radius:20px;width:800px;height:600px;margin:auto;position:relative;border:1px solid #a7a7b7;padding-top:20px;padding-left:20px;padding-right:20px;box-shadow:2.4px 2.4px 3.2px rgba(0,0,0,.15)}.bottom-element[data-v-033cb069]{position:absolute;bottom:20px}.aside-logo[data-v-4621ae0f]{display:block;height:100px;line-height:100px;font-size:24px;font-weight:700;margin:auto;background-color:hsla(60,34%,87%,.98);text-align:center}.mg-header[data-v-2a93102c]{padding-left:20px;height:100px;line-height:100px;position:relative}.mg-connect-status[data-v-2a93102c]{font-weight:700;font-size:20px;margin-right:15px;display:inline-block}.mg-connect-button[data-v-2a93102c]{display:inline-block;left:40%;position:absolute}.container-mg-header[data-v-343369a6]{border-image-source:radial-gradient(60% 60%,transparent 0,transparent 100%,#d2c1c1 0);border-image-slice:1;border-width:1px;border-style:solid}.container-main[data-v-343369a6]{margin-top:10px}.aside[data-v-343369a6]{padding:0;margin:0}.progress-name[data-v-00958a9f]{display:inline-block;font-weight:700;font-size:20px;padding-right:10px}.progress-item-name[data-v-00958a9f]{font-size:18px}.cell-item[data-v-33a6d858]{font-size:16px}.middleware-data[data-v-430e8d16]{padding:0;margin:0}.el-table[data-v-430e8d16] .warning-row{--el-table-tr-bg-color:var(--el-color-warning-light-9)}.el-extra[data-v-bfcb9ede]{display:inline-block;margin-right:20px}.framework-data[data-v-2a591470]{padding:0;margin:0}.el-table[data-v-2a591470] .warning-row{--el-table-tr-bg-color:var(--el-color-warning-light-9)}.el-extra[data-v-8e45a2be]{display:inline-block;margin-right:20px}.type-name[data-v-64f4a4d0]{font-weight:bolder;font-size:18px}.data-menu-select[data-v-64f4a4d0]{margin-bottom:20px}html.dark{color-scheme:dark;--el-color-primary:#5a5aad;--el-color-success:#30541e;--el-text-color-primary:#fff}html.dark .el-button:hover{background-color:#606ea9;border-color:#606ea9}html.dark .el-card{--el-card-bg-color:var(--el-bg-color-overlay)}html.dark .el-empty{--el-empty-fill-color-0:var(--el-color-black);--el-empty-fill-color-1:#4b4b52;--el-empty-fill-color-2:#36383d;--el-empty-fill-color-3:#1e1e20;--el-empty-fill-color-4:#262629;--el-empty-fill-color-5:#202124;--el-empty-fill-color-6:#212224;--el-empty-fill-color-7:#1b1c1f;--el-empty-fill-color-8:#1c1d1f;--el-empty-fill-color-9:#18181a} -------------------------------------------------------------------------------- /server/server/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/server/server/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /server/server/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | Router

-------------------------------------------------------------------------------- /server/server/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | Router
-------------------------------------------------------------------------------- /webfrontend/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | not ie 11 5 | -------------------------------------------------------------------------------- /webfrontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /webfrontend/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | -------------------------------------------------------------------------------- /webfrontend/README.md: -------------------------------------------------------------------------------- 1 | # webfrontend 2 | 3 | ## Project setup 4 | ``` 5 | pnpm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | pnpm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | pnpm run build 16 | ``` 17 | 18 | ### Customize configuration 19 | See [Configuration Reference](https://cli.vuejs.org/config/). 20 | -------------------------------------------------------------------------------- /webfrontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /webfrontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webfrontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "@vueuse/core": "^11.2.0", 11 | "axios": "^1.7.7", 12 | "core-js": "^3.8.3", 13 | "element-plus": "^2.8.7", 14 | "vue": "^3.2.13", 15 | "vue-router": "^4.0.3" 16 | }, 17 | "devDependencies": { 18 | "@vue/cli-plugin-babel": "~5.0.0", 19 | "@vue/cli-plugin-router": "~5.0.0", 20 | "@vue/cli-plugin-typescript": "~5.0.0", 21 | "@vue/cli-service": "~5.0.0", 22 | "typescript": "~5.6.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /webfrontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/webfrontend/public/favicon.ico -------------------------------------------------------------------------------- /webfrontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Router 9 | 10 | 11 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /webfrontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | 21 | -------------------------------------------------------------------------------- /webfrontend/src/api/jdwp.ts: -------------------------------------------------------------------------------- 1 | import {routerRequest} from "@/utils/requests" 2 | import {ElMessage} from "element-plus"; 3 | 4 | export function apiGetJDWPStatus(): Promise { 5 | return routerRequest({ 6 | method: 'GET', 7 | url: '/jdwp/status' 8 | }).then(routerResponse => { 9 | return new Promise(resolve => resolve(routerResponse.code === 200)) 10 | }) 11 | } 12 | 13 | export function apiConnectJDWP(): Promise { 14 | return routerRequest({ 15 | method: 'POST', 16 | url: '/jdwp/connect' 17 | }).then(routerResponse => { 18 | if (routerResponse.code === 400) { 19 | ElMessage({ 20 | type: 'error', 21 | message: routerResponse.msg, 22 | }) 23 | } 24 | return new Promise(resolve => resolve(routerResponse.code === 200)) 25 | }) 26 | } 27 | 28 | export function apiCloseJDWP() { 29 | return routerRequest({ 30 | method: "DELETE", 31 | url: '/jdwp/close' 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /webfrontend/src/api/progress.ts: -------------------------------------------------------------------------------- 1 | import {routerRequest} from "@/utils/requests" 2 | import {GetBaseUrl} from "@/config" 3 | 4 | export class Progress { 5 | id: number 6 | name: string 7 | percentage: number 8 | message: string 9 | error: string 10 | fail: boolean 11 | 12 | constructor(response: any) { 13 | this.id = response !== null ? response.id : -1 14 | let namespaceList = response.taskName.split(".") 15 | this.name = response !== null ? namespaceList[namespaceList.length - 1] : "" 16 | this.percentage = response !== null ? Math.floor((response.current / response.count) * 100) : 0 17 | if (this.percentage === 100) { 18 | this.message = '完成分析' 19 | } else { 20 | this.message = response !== null ? response.message : "" 21 | } 22 | this.fail = response !== null ? response.fail : false 23 | this.error = response !== null ? response.error : "" 24 | } 25 | } 26 | 27 | export function apiGetProgress(): Promise { 28 | return routerRequest({ 29 | url: '/progress/getall', 30 | method: 'GET' 31 | }).then(routerResponse => { 32 | let result: Progress[] = [] 33 | for (let rawProgress of routerResponse.msg) { 34 | result.push(new Progress(rawProgress)) 35 | } 36 | return new Promise(resolve => resolve(result)) 37 | }) 38 | } 39 | 40 | export function GetCurrentProject(): Promise { 41 | return routerRequest({ 42 | url: '/project/current', 43 | method: 'GET' 44 | }).then(routerResponse => { 45 | return new Promise(resolve => resolve(routerResponse.code === 200)) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /webfrontend/src/api/project.ts: -------------------------------------------------------------------------------- 1 | import {routerRequest, RouterResponse} from "@/utils/requests" 2 | import {ElMessage} from "element-plus"; 3 | 4 | export class Project { 5 | id: string 6 | name: string 7 | hostname: string 8 | port: number 9 | createTime: Date 10 | private empty: boolean 11 | public static default: Project = new Project(null) 12 | 13 | constructor(response: any) { 14 | this.id = response !== null ? response.id : "" 15 | this.hostname = response !== null ? response.hostname : "" 16 | this.port = response !== null ? response.port : -1 17 | this.name = response !== null ? response.alias : "" 18 | this.createTime = response !== null ? response.createTime : new Date() 19 | this.empty = response === null 20 | } 21 | 22 | public isEmpty() { 23 | return this.empty 24 | } 25 | } 26 | 27 | export function apiGetAllProject(): Promise { 28 | return routerRequest({ 29 | url: '/project/get/all', 30 | method: 'get' 31 | }).then(routerResponse => { 32 | let result: Project[] = [] 33 | for (let project of routerResponse.msg) { 34 | result.push(new Project(project)) 35 | } 36 | return new Promise(resolve => resolve(result)) 37 | }) 38 | } 39 | 40 | 41 | export function apiCreateProject(project: Project | any): Promise { 42 | return routerRequest({ 43 | url: '/project/creat', 44 | method: 'post', 45 | data: { 46 | alias: project.name, 47 | hostname: project.hostname, 48 | port: project.port, 49 | createTime: project.createTime 50 | }, 51 | }).then(routerResponse => { 52 | return new Promise(resolve => { 53 | ElMessage({ 54 | type: routerResponse.code === 200 ? "success" : "error", 55 | message: routerResponse.msg, 56 | }) 57 | resolve(routerResponse.code === 200) 58 | }) 59 | }) 60 | } 61 | 62 | export function apiSelectProject(id: string) { 63 | return routerRequest({ 64 | url: '/project/select/' + id, 65 | method: 'post', 66 | }) 67 | } 68 | 69 | export function apiLogoutProject() { 70 | return routerRequest({ 71 | url: '/project/logout', 72 | method: 'post', 73 | }) 74 | } 75 | 76 | export function apiGetCurrentProject(): Promise { 77 | return routerRequest({ 78 | url: '/project/current', 79 | method: 'GET', 80 | }).then(routerResponse => { 81 | return new Promise(resolve => resolve(new Project(routerResponse.msg))) 82 | }) 83 | } 84 | 85 | export function apiDeleteProject(id: string) { 86 | return routerRequest({ 87 | url: '/project/delete/' + id, 88 | method: 'DELETE' 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /webfrontend/src/api/task.ts: -------------------------------------------------------------------------------- 1 | import {routerRequest} from "@/utils/requests" 2 | import {ElMessage} from "element-plus"; 3 | 4 | export function apiStartAnalysts(): Promise { 5 | return routerRequest({ 6 | method: 'POST', 7 | url: '/task/start' 8 | }).then(routerResponse => { 9 | return new Promise(resolve => { 10 | if (routerResponse.code === 400) { 11 | ElMessage({ 12 | type: 'error', 13 | message: routerResponse.msg, 14 | }) 15 | } 16 | resolve(routerResponse.code === 200) 17 | }) 18 | }) 19 | } 20 | 21 | export function apiAnalystStatus(): Promise { 22 | return routerRequest({ 23 | method: 'GET', 24 | url: '/task/status' 25 | }).then(routerResponse => { 26 | return new Promise(resolve => resolve(routerResponse.code === 200)) 27 | }) 28 | } 29 | 30 | export function apiStopAnalysts() { 31 | return routerRequest({ 32 | method: 'DELETE', 33 | url: '/task/stop' 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /webfrontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyo-w/router-router/882eaaddd05ef3282fe52e5fb046c36d03e9c900/webfrontend/src/assets/logo.png -------------------------------------------------------------------------------- /webfrontend/src/components/manager/FrameworkBox.vue: -------------------------------------------------------------------------------- 1 | 51 | 78 | 84 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/FrameworkData.vue: -------------------------------------------------------------------------------- 1 | 23 | 69 | 79 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/MgAside.vue: -------------------------------------------------------------------------------- 1 | 29 | 43 | 55 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/MgData.vue: -------------------------------------------------------------------------------- 1 | 10 | 25 | 28 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/MgHeader.vue: -------------------------------------------------------------------------------- 1 | 25 | 91 | 92 | 113 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/MiddlewareBox.vue: -------------------------------------------------------------------------------- 1 | 60 | 100 | 106 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/MiddlewareData.vue: -------------------------------------------------------------------------------- 1 | 29 | 87 | 97 | -------------------------------------------------------------------------------- /webfrontend/src/components/manager/ProgressItem.vue: -------------------------------------------------------------------------------- 1 | 21 | 39 | 40 | 52 | -------------------------------------------------------------------------------- /webfrontend/src/components/project/CreateProjectItem.vue: -------------------------------------------------------------------------------- 1 | 18 | 49 | 52 | -------------------------------------------------------------------------------- /webfrontend/src/components/project/ProjectBottom.vue: -------------------------------------------------------------------------------- 1 | 13 | 39 | 40 | 53 | -------------------------------------------------------------------------------- /webfrontend/src/components/project/ProjectNameIcon.vue: -------------------------------------------------------------------------------- 1 | 9 | 18 | 30 | -------------------------------------------------------------------------------- /webfrontend/src/components/project/ProjectProfiler.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | 16 | 19 | -------------------------------------------------------------------------------- /webfrontend/src/components/project/ProjectTitle.vue: -------------------------------------------------------------------------------- 1 | 7 | 14 | 33 | -------------------------------------------------------------------------------- /webfrontend/src/config.ts: -------------------------------------------------------------------------------- 1 | const Debug = true 2 | export function GetBaseUrl() { 3 | if (Debug) { 4 | return "127.0.0.1:9090" 5 | } else { 6 | return window.location.host 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /webfrontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import 'element-plus/dist/index.css' 5 | import ElementPlus from 'element-plus' 6 | import '@/theme/dark.css' 7 | 8 | const app = createApp(App) 9 | app.use(ElementPlus) 10 | app.use(router) 11 | app.mount('#app') 12 | -------------------------------------------------------------------------------- /webfrontend/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import {createRouter, createWebHashHistory, createWebHistory, RouteRecordRaw} from 'vue-router' 2 | import dashBoard from '@/views/DashBoard.vue' 3 | import mgIndex from '@/views/manger/Index.vue' 4 | import progress from '@/views/manger/Progress.vue' 5 | import mgProfile from '@/views/manger/Profile.vue' 6 | import mgData from '@/views/manger/Data.vue' 7 | import {GetCurrentProject} from "@/api/progress"; 8 | 9 | const routes: Array = [ 10 | { 11 | path: '/', 12 | name: '/', 13 | component: dashBoard, 14 | meta: { 15 | title: '面板' 16 | } 17 | }, { 18 | path: '/mg', 19 | name: 'manger', 20 | component: mgIndex, 21 | children: [ 22 | { 23 | path: 'progress', 24 | name: 'progress', 25 | component: progress, 26 | }, { 27 | path: 'profile', 28 | name: 'profile', 29 | component: mgProfile 30 | }, { 31 | path: 'data', 32 | name: 'data', 33 | component: mgData 34 | } 35 | ] 36 | } 37 | ] 38 | 39 | const router = createRouter({ 40 | history: createWebHashHistory(process.env.BASE_URL), 41 | routes 42 | }) 43 | 44 | router.beforeEach((to, from, next) => { 45 | if (to.name === '/') { 46 | next() 47 | return 48 | } 49 | if (!router.getRoutes().some(route => route.name === to.name)) { 50 | router.push('/mg/progress') 51 | return 52 | } 53 | GetCurrentProject().then(res => { 54 | if (res) { 55 | next() 56 | } else { 57 | router.push('/') 58 | } 59 | }) 60 | }); 61 | 62 | export default router 63 | -------------------------------------------------------------------------------- /webfrontend/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*.vue' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /webfrontend/src/theme/dark.css: -------------------------------------------------------------------------------- 1 | html.dark { 2 | color-scheme: dark; 3 | --el-color-primary: #5a5aad; 4 | --el-color-success: #30541e; 5 | /*--el-color-success-light-3: rgb(78.1, 141.8, 46.6);*/ 6 | /*--el-color-success-light-5: rgb(61.5, 107, 39);*/ 7 | /*--el-color-success-light-7: rgb(44.9, 72.2, 31.4);*/ 8 | /*--el-color-success-light-8: rgb(36.6, 54.8, 27.6);*/ 9 | /*--el-color-success-light-9: rgb(28.3, 37.4, 23.8);*/ 10 | /*--el-color-success-dark-2: rgb(133.4, 206.2, 97.4);*/ 11 | /*--el-color-warning: #e6a23c;*/ 12 | /*--el-color-warning-light-3: rgb(167, 119.4, 48);*/ 13 | /*--el-color-warning-light-5: #7d5b28;*/ 14 | /*--el-color-warning-light-7: rgb(83, 62.6, 32);*/ 15 | /*--el-color-warning-light-8: rgb(62, 48.4, 28);*/ 16 | /*--el-color-warning-light-9: rgb(41, 34.2, 24);*/ 17 | /*--el-color-warning-dark-2: rgb(235, 180.6, 99);*/ 18 | /*--el-color-danger: #f56c6c;*/ 19 | /*--el-color-danger-light-3: rgb(177.5, 81.6, 81.6);*/ 20 | /*--el-color-danger-light-5: rgb(132.5, 64, 64);*/ 21 | /*--el-color-danger-light-7: rgb(87.5, 46.4, 46.4);*/ 22 | /*--el-color-danger-light-8: rgb(65, 37.6, 37.6);*/ 23 | /*--el-color-danger-light-9: rgb(42.5, 28.8, 28.8);*/ 24 | /*--el-color-danger-dark-2: rgb(247, 137.4, 137.4);*/ 25 | /*--el-color-error: #f56c6c;*/ 26 | /*--el-color-error-light-3: rgb(177.5, 81.6, 81.6);*/ 27 | /*--el-color-error-light-5: rgb(132.5, 64, 64);*/ 28 | /*--el-color-error-light-7: rgb(87.5, 46.4, 46.4);*/ 29 | /*--el-color-error-light-8: rgb(65, 37.6, 37.6);*/ 30 | /*--el-color-error-light-9: rgb(42.5, 28.8, 28.8);*/ 31 | /*--el-color-error-dark-2: rgb(247, 137.4, 137.4);*/ 32 | /*--el-color-info: #909399;*/ 33 | /*--el-color-info-light-3: rgb(106.8, 108.9, 113.1);*/ 34 | /*--el-color-info-light-5: rgb(82, 83.5, 86.5);*/ 35 | /*--el-color-info-light-7: rgb(57.2, 58.1, 59.9);*/ 36 | /*--el-color-info-light-8: rgb(44.8, 45.4, 46.6);*/ 37 | /*--el-color-info-light-9: rgb(32.4, 32.7, 33.3);*/ 38 | /*--el-color-info-dark-2: rgb(166.2, 168.6, 173.4);*/ 39 | /*--el-box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.36), 0px 8px 20px rgba(0, 0, 0, 0.72);*/ 40 | /*--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.72);*/ 41 | /*--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.72);*/ 42 | /*--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.72), 0px 12px 32px #000000, 0px 8px 16px -8px #000000;*/ 43 | /*--el-bg-color-page: #0a0a0a;*/ 44 | /*--el-bg-color: #141414;*/ 45 | /*--el-bg-color-overlay: #1d1e1f;*/ 46 | --el-text-color-primary: #ffffff; 47 | /*--el-text-color-regular: #CFD3DC;*/ 48 | /*--el-text-color-secondary: #A3A6AD;*/ 49 | /*--el-text-color-placeholder: #8D9095;*/ 50 | /*--el-text-color-disabled: #6C6E72;*/ 51 | /*--el-border-color-darker: #636466;*/ 52 | /*--el-border-color-dark: #58585B;*/ 53 | /*--el-border-color: #4C4D4F;*/ 54 | /*--el-border-color-light: #414243;*/ 55 | /*--el-border-color-lighter: #363637;*/ 56 | /*--el-border-color-extra-light: #2B2B2C;*/ 57 | /*--el-fill-color-darker: #424243;*/ 58 | /*--el-fill-color-dark: #39393A;*/ 59 | /*--el-fill-color: #303030;*/ 60 | /*--el-fill-color-light: #262727;*/ 61 | /*--el-fill-color-lighter: #1D1D1D;*/ 62 | /*--el-fill-color-extra-light: #191919;*/ 63 | /*--el-fill-color-blank: transparent;*/ 64 | /*--el-mask-color: rgba(0, 0, 0, 0.8);*/ 65 | /*--el-mask-color-extra-light: rgba(0, 0, 0, 0.3)*/ 66 | } 67 | 68 | html.dark .el-button:hover { 69 | background-color: #606ea9; 70 | border-color: #606ea9; 71 | } 72 | 73 | html.dark .el-card { 74 | --el-card-bg-color: var(--el-bg-color-overlay) 75 | } 76 | 77 | html.dark .el-empty { 78 | --el-empty-fill-color-0: var(--el-color-black); 79 | --el-empty-fill-color-1: #4b4b52; 80 | --el-empty-fill-color-2: #36383d; 81 | --el-empty-fill-color-3: #1e1e20; 82 | --el-empty-fill-color-4: #262629; 83 | --el-empty-fill-color-5: #202124; 84 | --el-empty-fill-color-6: #212224; 85 | --el-empty-fill-color-7: #1b1c1f; 86 | --el-empty-fill-color-8: #1c1d1f; 87 | --el-empty-fill-color-9: #18181a 88 | } 89 | -------------------------------------------------------------------------------- /webfrontend/src/utils/requests.ts: -------------------------------------------------------------------------------- 1 | import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from "axios" 2 | import {GetBaseUrl} from "@/config" 3 | 4 | const nativeRequest: AxiosInstance = axios.create({ 5 | baseURL: 'http://' + GetBaseUrl(), 6 | withCredentials: true, 7 | timeout: 5000 8 | }) 9 | 10 | export class RouterResponse { 11 | msg: any 12 | code: number 13 | 14 | constructor(axiosResponse: AxiosResponse) { 15 | this.msg = axiosResponse.data.msg 16 | this.code = axiosResponse.data.code 17 | } 18 | } 19 | 20 | export const routerRequest = (config: AxiosRequestConfig): Promise => { 21 | return nativeRequest(config).then(res => { 22 | return new Promise(resolve => { 23 | resolve(new RouterResponse(res)) 24 | }) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /webfrontend/src/views/DashBoard.vue: -------------------------------------------------------------------------------- 1 | 22 | 49 | 71 | -------------------------------------------------------------------------------- /webfrontend/src/views/manger/Data.vue: -------------------------------------------------------------------------------- 1 | 28 | 60 | 70 | -------------------------------------------------------------------------------- /webfrontend/src/views/manger/Index.vue: -------------------------------------------------------------------------------- 1 | 16 | 21 | 38 | -------------------------------------------------------------------------------- /webfrontend/src/views/manger/Profile.vue: -------------------------------------------------------------------------------- 1 | 43 | 50 | 55 | -------------------------------------------------------------------------------- /webfrontend/src/views/manger/Progress.vue: -------------------------------------------------------------------------------- 1 | 9 | 37 | 39 | -------------------------------------------------------------------------------- /webfrontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "moduleResolution": "node", 8 | "skipLibCheck": true, 9 | "esModuleInterop": true, 10 | "allowSyntheticDefaultImports": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "useDefineForClassFields": true, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "types": [ 16 | "webpack-env" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "esnext", 25 | "dom", 26 | "dom.iterable", 27 | "scripthost" 28 | ] 29 | }, 30 | "include": [ 31 | "src/**/*.ts", 32 | "src/**/*.tsx", 33 | "src/**/*.vue", 34 | "tests/**/*.ts", 35 | "tests/**/*.tsx" 36 | ], 37 | "exclude": [ 38 | "node_modules" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /webfrontend/vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | module.exports = defineConfig({ 3 | transpileDependencies: true 4 | }) 5 | --------------------------------------------------------------------------------