├── .circleci └── config.yml ├── .eslintignore ├── .eslintrc.json ├── .github ├── CODEOWNERS └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .pre-commit-config.yaml ├── .prettierignore ├── .prettierrc.json ├── Contributor-Agreement.md ├── LICENSE ├── README.md ├── bin └── init.gradle ├── catalog-info.yaml ├── config.default.json ├── jest.config.js ├── lib ├── call-graph.ts ├── class-parsing.ts ├── classpath.ts ├── config.ts ├── debug.ts ├── errors.ts ├── fetch-snyk-java-call-graph-generator.ts ├── gradle-wrapper.ts ├── index.ts ├── java-wrapper.ts ├── metrics.ts ├── mvn-wrapper-legacy.ts ├── mvn-wrapper.ts ├── promisified-fs-glob.ts └── sub-process.ts ├── package.json ├── test ├── .eslintrc.json ├── fixtures │ ├── call-graph.txt │ ├── example-java-project │ │ └── target │ │ │ ├── classes │ │ │ └── io │ │ │ │ └── github │ │ │ │ └── todolist │ │ │ │ └── core │ │ │ │ ├── domain │ │ │ │ ├── Priority.class │ │ │ │ ├── Todo.class │ │ │ │ └── User.class │ │ │ │ ├── repository │ │ │ │ ├── api │ │ │ │ │ ├── TodoRepository.class │ │ │ │ │ └── UserRepository.class │ │ │ │ └── impl │ │ │ │ │ ├── TodoRepositoryImpl.class │ │ │ │ │ └── UserRepositoryImpl.class │ │ │ │ └── service │ │ │ │ ├── api │ │ │ │ ├── TodoService.class │ │ │ │ └── UserService.class │ │ │ │ └── impl │ │ │ │ ├── TodoServiceImpl.class │ │ │ │ └── UserServiceImpl.class │ │ │ └── todolist-core-1.0-SNAPSHOT.jar │ ├── expected-call-graph.json │ ├── java-goof-expected-jars.json │ ├── java-goof-mvn-dependency-plugin-output-line-feed-and-carriage-return.txt │ ├── java-goof-mvn-dependency-plugin-output-line-feed.txt │ ├── java-goof-mvn-exec-output-line-feed-and-carriage-return.txt │ ├── java-goof-mvn-exec-output-line-feed.txt │ ├── java-reachability-playground │ │ ├── build.gradle │ │ ├── build │ │ │ ├── classes │ │ │ │ └── java │ │ │ │ │ └── main │ │ │ │ │ ├── Butler.class │ │ │ │ │ └── Unzipper.class │ │ │ ├── distributions │ │ │ │ ├── java-reachable-goof-1.0-SNAPSHOT.tar │ │ │ │ └── java-reachable-goof-1.0-SNAPSHOT.zip │ │ │ ├── libs │ │ │ │ └── java-reachable-goof-1.0-SNAPSHOT.jar │ │ │ ├── scripts │ │ │ │ ├── java-reachable-goof │ │ │ │ └── java-reachable-goof.bat │ │ │ └── tmp │ │ │ │ ├── compileJava │ │ │ │ └── source-classes-mapping.txt │ │ │ │ └── jar │ │ │ │ └── MANIFEST.MF │ │ ├── init.gradle │ │ ├── pom.xml │ │ ├── settings.xml │ │ └── target │ │ │ ├── classes │ │ │ ├── Butler.class │ │ │ └── Unzipper.class │ │ │ └── maven-status │ │ │ └── maven-compiler-plugin │ │ │ └── compile │ │ │ └── default-compile │ │ │ ├── createdFiles.lst │ │ │ └── inputFiles.lst │ ├── snyk-call-graph-generator.txt │ └── snyk-call-graph-generator_old.txt ├── integration │ ├── e2e-run_gradle.test.ts │ ├── e2e-run_mvn.test.ts │ └── fetch-snyk-java-call-graph-generator.test.ts ├── lib │ ├── call-graph.test.ts │ ├── classpath.test.ts │ ├── fetch-snyk-java-call-graph-generator.test.ts │ ├── gradle-wrapper.test.ts │ ├── index.test.ts │ ├── java-wrapper.test.ts │ ├── metrics.test.ts │ ├── mvn-wrapper-legacy.test.ts │ └── mvn-wrapper.test.ts └── tsconfig.json ├── tsconfig.json └── tslint.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | win: circleci/windows@2.2.0 5 | prodsec: snyk/prodsec-orb@1.0 6 | 7 | defaults: &defaults_unix 8 | resource_class: small 9 | docker: 10 | - image: node:14 11 | working_directory: ~/snyk-java-call-graph-builder 12 | 13 | windows_defaults: &defaults_windows 14 | environment: 15 | npm_config_loglevel: silent 16 | executor: 17 | name: win/default 18 | working_directory: ~/snyk-java-call-graph-builder 19 | 20 | commands: 21 | install_deps: 22 | description: Install dependencies 23 | steps: 24 | - checkout 25 | - restore_cache: 26 | keys: 27 | - v1-npm-cache-{{ checksum "package.json" }} 28 | - v1-npm-cache- 29 | - run: 30 | name: Use snyk-main npmjs user 31 | command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc 32 | - run: 33 | name: Install dependencies 34 | command: npm install 35 | - save_cache: 36 | key: v1-npm-cache-{{ checksum "package.json" }} 37 | paths: 38 | - ~/.npm 39 | - persist_to_workspace: 40 | root: . 41 | paths: 42 | - node_modules/ 43 | install_deps_windows: 44 | description: Install dependencies on Windows 45 | steps: 46 | - run: 47 | name: Install dependencies 48 | command: npm install 49 | checkout_and_merge: 50 | steps: 51 | - checkout 52 | - run: 53 | name: Checkout master 54 | command: git checkout origin/master 55 | - run: 56 | name: Merge test branch 57 | command: | 58 | git config user.name "CircleCI" 59 | git config user.email "noop" 60 | git merge --no-edit "$CIRCLE_BRANCH" 61 | - attach_workspace: 62 | at: ~/snyk-java-call-graph-builder 63 | install_gradle_windows: 64 | description: Install gradle 65 | steps: 66 | - run: | 67 | choco install gradle 68 | install_sdkman: 69 | description: Install SDKMAN 70 | steps: 71 | - run: 72 | name: Installing SDKMAN 73 | command: | 74 | curl -s "https://get.sdkman.io?rcupdate=false" | bash 75 | echo -e '\nsource "/home/circleci/.sdkman/bin/sdkman-init.sh"' >> $BASH_ENV 76 | source $BASH_ENV 77 | install_gradle_unix: 78 | description: Install gradle 79 | steps: 80 | - run: 81 | name: Installing Gradle 82 | command: sdk install gradle 83 | install_maven_unix: 84 | steps: 85 | - run: 86 | name: Install java and maven 87 | command: | 88 | sudo apt-get update 89 | sudo apt-get install -y openjdk-8-jdk maven 90 | install_maven_windows: 91 | description: Install maven 92 | steps: 93 | - run: choco install maven 94 | jobs: 95 | install: 96 | <<: *defaults_unix 97 | steps: 98 | - install_deps 99 | lint: 100 | <<: *defaults_unix 101 | steps: 102 | - checkout 103 | - attach_workspace: 104 | at: ~/snyk-java-call-graph-builder 105 | - run: 106 | name: Run tests 107 | command: npm run lint 108 | test-unit-unix: 109 | <<: *defaults_unix 110 | docker: 111 | - image: circleci/node:14 112 | steps: 113 | - checkout 114 | - setup_remote_docker 115 | - attach_workspace: 116 | at: ~/snyk-java-call-graph-builder 117 | - run: 118 | name: Run unit tests 119 | command: npm run test:unit 120 | test-integration-unix: 121 | <<: *defaults_unix 122 | docker: 123 | - image: circleci/node:14 124 | steps: 125 | - checkout 126 | - setup_remote_docker 127 | - install_maven_unix 128 | - install_sdkman 129 | - install_gradle_unix 130 | - attach_workspace: 131 | at: ~/snyk-java-call-graph-builder 132 | - run: 133 | name: Run integration tests 134 | command: | 135 | npm run test:integration 136 | test-unit-windows: 137 | <<: *defaults_windows 138 | steps: 139 | - run: git config --global core.autocrlf false 140 | - checkout 141 | - install_deps_windows 142 | - run: 143 | name: Run unit tests 144 | command: npm run test:unit 145 | test-integration-windows: 146 | <<: *defaults_windows 147 | steps: 148 | - run: git config --global core.autocrlf false 149 | - checkout 150 | - install_deps_windows 151 | - install_maven_windows 152 | - install_gradle_windows 153 | - run: 154 | name: Run integration tests 155 | command: npm run test:integration 156 | build: 157 | <<: *defaults_unix 158 | steps: 159 | - checkout_and_merge 160 | - run: 161 | name: Use snyk-main npmjs user 162 | command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc 163 | - run: 164 | name: Install dependencies 165 | command: npm install 166 | - run: 167 | name: Build 168 | command: npm run build 169 | release: 170 | <<: *defaults_unix 171 | steps: 172 | - checkout 173 | - run: 174 | name: Install dependencies 175 | command: npm install 176 | - run: 177 | name: Build 178 | command: npm run build 179 | - run: 180 | name: Release on GitHub 181 | command: npx semantic-release 182 | 183 | workflows: 184 | version: 2 185 | test_and_release: 186 | jobs: 187 | - prodsec/secrets-scan: 188 | name: Scan repository for secrets 189 | context: 190 | - snyk-bot-slack 191 | channel: os-team-managed-alerts 192 | 193 | - install: 194 | name: Install 195 | context: nodejs-install 196 | filters: 197 | branches: 198 | ignore: 199 | - master 200 | - lint: 201 | name: Lint 202 | context: nodejs-install 203 | requires: 204 | - Install 205 | filters: 206 | branches: 207 | ignore: 208 | - master 209 | - build: 210 | name: Build 211 | requires: 212 | - Install 213 | filters: 214 | branches: 215 | ignore: 216 | - master 217 | - test-unit-unix: 218 | name: Unit Tests 219 | context: nodejs-install 220 | requires: 221 | - Install 222 | filters: 223 | branches: 224 | ignore: 225 | - master 226 | - test-integration-unix: 227 | name: Integration Tests 228 | context: nodejs-install 229 | requires: 230 | - Install 231 | filters: 232 | branches: 233 | ignore: 234 | - master 235 | - test-unit-windows: 236 | name: Unit Tests Windows 237 | context: nodejs-install 238 | filters: 239 | branches: 240 | ignore: 241 | - master 242 | # CircleCI struggles to complete gradle integration test on Windows, 243 | # while it works perfectly when SSHed into the machine. Therefore skip of 244 | # the test on platform feels better than skip of the whole gradle 245 | # integration test. 246 | #- test-integration-windows: 247 | #name: Integration Tests Windows 248 | #context: nodejs-install 249 | #filters: 250 | #branches: 251 | #ignore: 252 | #- master 253 | - release: 254 | name: Release to GitHub 255 | context: nodejs-lib-release 256 | filters: 257 | branches: 258 | only: 259 | - master 260 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "project": "./tsconfig.json" 5 | }, 6 | "env": { 7 | "node": true, 8 | "es6": true, 9 | "jest": true 10 | }, 11 | "plugins": ["@typescript-eslint"], 12 | "extends": [ 13 | "eslint:recommended", 14 | "plugin:@typescript-eslint/eslint-recommended", 15 | "plugin:@typescript-eslint/recommended", 16 | "prettier", 17 | "prettier/@typescript-eslint" 18 | ], 19 | "rules": { 20 | "@typescript-eslint/explicit-function-return-type": "off", 21 | "@typescript-eslint/no-explicit-any": "off", 22 | "@typescript-eslint/no-empty-function": "warn", 23 | 24 | // non-null assertions compromise the type safety somewhat, but many 25 | // our types are still imprecisely defined and we don't use noImplicitAny 26 | // anyway, so for the time being assertions are allowed 27 | "@typescript-eslint/no-non-null-assertion": "warn", 28 | 29 | "@typescript-eslint/no-var-requires": "off", 30 | "@typescript-eslint/no-use-before-define": "off", 31 | "@typescript-eslint/no-unused-vars": "error", 32 | "no-prototype-builtins": "off", 33 | "require-atomic-updates": "off", 34 | "no-buffer-constructor": "error" 35 | }, 36 | "overrides": [ 37 | { 38 | "files": ["*.ts"], 39 | "rules": { 40 | "id-blacklist": ["error", "exports"] // in TS, use "export" instead of Node's "module.exports" 41 | } 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @snyk/os-managed 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | - [ ] Tests written and linted [ℹ︎](https://github.com/snyk/general/wiki/Tests) 2 | - [ ] Documentation written [ℹ︎](https://github.com/snyk/general/wiki/Documentation) 3 | - [ ] Commit history is tidy [ℹ︎](https://github.com/snyk/general/wiki/Git) 4 | 5 | ### What this does 6 | 7 | _Explain why this PR exists_ 8 | 9 | ### Notes for the reviewer 10 | 11 | _Instructions on how to run this locally, background context, what to review, questions…_ 12 | 13 | ### More information 14 | 15 | - [Jira ticket SC-0000](https://snyksec.atlassian.net/browse/SC-0000) 16 | - [Link to documentation](https://github.com/snyk/java-call-graph-builder/wiki/) 17 | 18 | ### Screenshots 19 | 20 | _Visuals that may help the reviewer_ 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .npmrc 4 | # output 5 | dist 6 | .DS_Store 7 | *.log 8 | package-lock.json 9 | yarn.lock 10 | .eslintcache 11 | **/.gradle/** 12 | .idea/ 13 | .vscode 14 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/gitleaks/gitleaks 3 | rev: v8.16.1 4 | hooks: 5 | - id: gitleaks 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | test/fixtures/**/* 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "htmlWhitespaceSensitivity": "ignore" 6 | } 7 | -------------------------------------------------------------------------------- /Contributor-Agreement.md: -------------------------------------------------------------------------------- 1 | # Snyk Java call graph builder tool contributor agreement 2 | 3 | This Snyk Java call graph builder tool Agreement (this **"Agreement"**) applies to any Contribution you make to any Work. 4 | 5 | This is a binding legal agreement on you and any organization you represent. If you are signing this Agreement on behalf of your employer or other organization, you represent and warrant that you have the authority to agree to this Agreement on behalf of the organization. 6 | 7 | ## 1. Definitions 8 | 9 | **"Contribution"** means any original work, including any modification of or addition to an existing work, that you submit to Snyk Java call graph builder tool repo in any manner for inclusion in any Work. 10 | 11 | **"Snyk", "we"** and **"use"** means Snyk Ltd. 12 | 13 | **"Work"** means any project, work or materials owned or managed by Snyk Ltd. 14 | 15 | **"You"** and **"your"** means you and any organization on whose behalf you are entering this Agreement. 16 | 17 | ## 2. Copyright Assignment, License and Waiver 18 | 19 | **(a) Assignment.** By submitting a Contribution, you assign to Snyk all right, title and interest in any copright you have in the Contribution, and you waive any rights, including any moral rights, database rights, etc., that may affect your ownership of the copyright in the Contribution. 20 | 21 | **(b) License to Snyk.** If your assignment in Section 2(a) is ineffective for any reason, you grant to us and to any recipient of any Work distributed by use, a perpetual, worldwide, transferable, non-exclusive, no-charge, royalty-free, irrevocable, and sublicensable licence to use, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Contributions and any derivative work created based on a Contribution. If your license grant is ineffective for any reason, you irrevocably waive and covenant to not assert any claim you may have against us, our successors in interest, and any of our direct or indirect licensees and customers, arising out of our, our successors in interest's, or any of our direct or indirect licensees' or customers' use, reproduction, preparation of derivative works, public display, public performance, sublicense, and distribution of a Contribution. You also agree that we may publicly use your name and the name of any organization on whose behalf you're entering into this Agreement in connection with publicizing the Work. 22 | 23 | **(c) License to you.** We grant to you a perpetual, worldwide, transferable, non-exclusive, no-charge, royalty-free, irrevocable, and sublicensable license to use, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute a Contribution and any derivative works you create based on a Contribution. 24 | 25 | ## 3. Patent License 26 | 27 | You grant to us and to any recipient of any Work distributed by us, a perpetual, worldwide, transferable, non-exclusive, no-charge, royalty-free, irrevocable, and sublicensable patent license to make, have made, use, sell, offer to sell, import, and otherwise transfer the Contribution in whole or in part, along or included in any Work under any patent you own, or license from a third party, that is necessarily infringed by the Contribution or by combination of the Contribution with any Work. 28 | 29 | ## 4. Your Representation and Warranties. 30 | 31 | By submitting a Contribution, you represent and warrant that: (a) each Contribution you submit is an original work and you can legally grant the rights set out in this Agreement; (b) the Contribution does not, and any exercise of the rights granted by you will not, infringe any third party's intellectual property or other right; and (c) you are not aware of any claims, suits, or actions pertaining to the Contribution. You will notify us immediately if you become aware or have reason to believe that any of your representations and warranties is or becomes inaccurate. 32 | 33 | ##5. Intellectual Property 34 | Except for the assignment and licenses set forth in this Agreement, this Agreement does not transfer any right, title or interest in any intellectual property right of either party to the other. If you choose to provide us with suggestions, ideas for improvement, recommendations or other feedback, on any Work we may use your feedback without any restriction or payment. 35 | 36 | ## Miscellaneous 37 | 38 | English law governs this Agreement, excluding any applicable conflict of laws rules or principles, and the parties agree to the exclusive jurisdiction of the courts in England, UK. This Agreement does not create a partnership, agency relationship, or joint venture between the parties. We may assign this Agreement without notice or restriction. If any provision of this Agreement is unenforcable, that provision will be modified to render it enforceable to the extent possible to effect the parties' intention and the remaining provisions will not be affected. The parties may amend this Agreement only in a written amendment signed by both parties. This Agreement comprises the parties' entire agreement relating to the subject matter of this Agreement. 39 | 40 | **Agreed and accepted on my behalf and on behalf of my organization** 41 | 42 | Our contributor agreement is based on the [mongoDB contributor agreement](https://www.mongodb.com/legal/contributor-agreement). 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Snyk Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Snyk logo](https://snyk.io/style/asset/logo/snyk-print.svg) 2 | 3 | *** 4 | 5 | [![Known Vulnerabilities](https://snyk.io/test/github/snyk/java-call-graph-builder/badge.svg?targetFile=package.json)](https://snyk.io/test/github/snyk/java-call-graph-builder?targetFile=package.json) 6 | 7 | 8 | Snyk helps you find, fix and monitor for known vulnerabilities in your dependencies, both on an ad hoc basis and as part of your CI (Build) system. 9 | 10 | ![Snyk logo](https://snyk.io/style/asset/logo/snyk-print.svg) 11 | 12 | 13 | ## Snyk Java Call Graph Builder 14 | 15 | This package helps build a function call graph for a maven compiled artifact. 16 | It is an internal component intended for use by our [CLI maven plugin](https://github.com/snyk/snyk-mvn-plugin). 17 | 18 | # Support 19 | 20 | ❌ Not supported 21 | ❓ No issues expected but not regularly tested 22 | ✅ Supported and verified with tests 23 | 24 | ## Supported OS 25 | 26 | | OS | Supported | 27 | |--------|------------| 28 | | Linux | ✅ | 29 | | OSX | ️✅ | 30 | | Windows| ️✅ | 31 | 32 | ## Supported Node versions 33 | 34 | | Node | Supported | 35 | |-------|------------| 36 | | 8 | ✅ | 37 | | 10 | ✅ | 38 | | 12 | ✅ | 39 | 40 | ## Supported Java & Maven versions 41 | 42 | | Java / Maven|3.6.* | 43 | |----------------|---| 44 | | 8 (LTS) | ✅ | 45 | | 9 | ✅ | 46 | | 10 | ✅ | 47 | | 11 (LTS) | ✅ | 48 | | 12 | ✅ | 49 | | 13 | ✅ | 50 | -------------------------------------------------------------------------------- /bin/init.gradle: -------------------------------------------------------------------------------- 1 | allprojects { everyProj -> 2 | 3 | task printClasspath { 4 | doLast { 5 | def classPath = [].toSet(); 6 | 7 | pluginManager.withPlugin('java') { 8 | classPath = sourceSets.main.runtimeClasspath.asPath 9 | } 10 | 11 | if (!classPath) { 12 | pluginManager.withPlugin('android') { 13 | def androidBootClasspath = android.getBootClasspath()[0] 14 | def cp = [androidBootClasspath]; 15 | 16 | def confAttrSpec = [:] 17 | def configuredDimensionList = [] 18 | if (project.hasProperty('confAttrs')) { 19 | confAttrSpec = confAttrs.toLowerCase().split(',').collectEntries { [(it.split(':')[0]) : it.split(':')[1]] } 20 | configuredDimensionList = android.flavorDimensionList.findAll { confAttrSpec[it] } 21 | } 22 | 23 | project.android.applicationVariants.all { v -> 24 | // remove classpath for unused buildTypes 25 | if (confAttrSpec['buildtype'] && v.buildType.getName() != confAttrSpec['buildtype']) { 26 | return 27 | } 28 | 29 | // remove classpath for unused dimensions 30 | if (configuredDimensionList) { 31 | def usedFlavors = configuredDimensionList.findAll { 32 | v.flavorName.toLowerCase() == confAttrSpec[it] 33 | } 34 | if (!usedFlavors) { 35 | return; 36 | } 37 | } 38 | 39 | v.getCompileClasspath(null).getFiles().each { 40 | File f -> 41 | cp.add(f.getAbsolutePath()) 42 | } 43 | v.javaCompile.classpath.getFiles().each { 44 | f -> cp.add(f) 45 | } 46 | 47 | cp.add(v.javaCompile.destinationDir.getAbsolutePath()) 48 | } 49 | classPath = cp.join(":") 50 | } 51 | } 52 | 53 | /* 54 | the `snykReachabilityClasspath` can be declared using a `ext` block 55 | in the projects build script 56 | 57 | e.g for java: 58 | 59 | ext { 60 | snykReachabilityClasspath = sourceSets.main.compileClasspath.asPath 61 | } 62 | 63 | It requires a path formatted string, e.g: 64 | 65 | 66 | */ 67 | if (!classPath && project.hasProperty('snykReachabilityClasspath')) { 68 | classPath = project.snykReachabilityClasspath 69 | } 70 | 71 | if (classPath) println(classPath) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: java-call-graph-builder 5 | annotations: 6 | github.com/project-slug: snyk/java-call-graph-builder 7 | github.com/team-slug: snyk/os-managed 8 | spec: 9 | type: external-library 10 | lifecycle: "-" 11 | owner: os-managed 12 | -------------------------------------------------------------------------------- /config.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "CALL_GRAPH_GENERATOR_URL": "https://storage.googleapis.com/snyk-java-callgraph-generator/W3jTdXePWDEk7sZmaxNxgDAPCXnzFa6AWsvgeEN7yg/callgraph-generator-1.6.4-jar-with-dependencies.jar", 3 | "CALL_GRAPH_GENERATOR_CHECKSUM": "6a66f4b5b141080bfd01f42f344f7a2fbc314c93d1fa4ba8931beabadd9e38bd", 4 | "_COMMENT": "use sha256 to generate CALL_GRAPH_GENERATOR_CHECKSUM" 5 | } 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | collectCoverageFrom: ['lib/**/*.ts'], 5 | coverageReporters: ['text-summary', 'html'], 6 | }; 7 | -------------------------------------------------------------------------------- /lib/call-graph.ts: -------------------------------------------------------------------------------- 1 | import { Graph } from '@snyk/graphlib'; 2 | import { removeParams, toFQclassName } from './class-parsing'; 3 | 4 | function getNodeLabel( 5 | functionCall: string, 6 | classPerJarMapping: { [index: string]: string }, 7 | ): {} { 8 | // com.ibm.wala.FakeRootClass:fakeRootMethod 9 | const [className, functionName] = functionCall.split(':'); 10 | const jarName = classPerJarMapping[className]; 11 | 12 | return { 13 | className, 14 | functionName, 15 | jarName, 16 | }; 17 | } 18 | 19 | export function buildCallGraph( 20 | input: string, 21 | classPerJarMapping: { [index: string]: string }, 22 | ): Graph { 23 | const graph = new Graph(); 24 | 25 | for (const line of input.trim().split('\n')) { 26 | const [caller, callee] = line 27 | .trim() 28 | .split(' -> ') 29 | .map(removeParams) 30 | .map(toFQclassName); 31 | graph.setNode(caller, getNodeLabel(caller, classPerJarMapping)); 32 | graph.setNode(callee, getNodeLabel(callee, classPerJarMapping)); 33 | graph.setEdge(caller, callee); 34 | } 35 | 36 | return graph; 37 | } 38 | -------------------------------------------------------------------------------- /lib/class-parsing.ts: -------------------------------------------------------------------------------- 1 | export function removeParams(functionCall: string): string { 2 | // com/ibm/wala/FakeRootClass.fakeRootMethod:()V 3 | return functionCall.split(':')[0]; 4 | } 5 | 6 | export function toFQclassName(functionCall: string) { 7 | // com/ibm/wala/FakeRootClass.fakeRootMethod -> com.ibm.wala.FakeRootClass:fakeRootMethod 8 | return functionCall.replace('.', ':').replace(/\//g, '.'); 9 | } 10 | -------------------------------------------------------------------------------- /lib/classpath.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | function canonicalize(rawClasspath: string): string { 4 | let sanitisedClassPath = rawClasspath.trim(); 5 | while (sanitisedClassPath.startsWith(path.delimiter)) { 6 | sanitisedClassPath = sanitisedClassPath.slice(1); 7 | } 8 | while (sanitisedClassPath.endsWith(path.delimiter)) { 9 | sanitisedClassPath = sanitisedClassPath.slice(0, -1); 10 | } 11 | return sanitisedClassPath; 12 | } 13 | 14 | export class ClassPath { 15 | private readonly value: string; 16 | 17 | constructor(classPath: string) { 18 | this.value = canonicalize(classPath); 19 | } 20 | 21 | public isEmpty(): boolean { 22 | return this.value.length === 0; 23 | } 24 | 25 | public concat(other: ClassPath): ClassPath { 26 | const elements = this.value.split(path.delimiter); 27 | const otherElements = other.value.split(path.delimiter); 28 | const newElements = Array.from( 29 | new Set(elements.concat(otherElements)).values(), 30 | ); 31 | return new ClassPath(newElements.join(path.delimiter)); 32 | } 33 | 34 | public toString(): string { 35 | return this.value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/config.ts: -------------------------------------------------------------------------------- 1 | import * as snykConfig from 'snyk-config'; 2 | import * as path from 'path'; 3 | 4 | interface Config { 5 | CALL_GRAPH_GENERATOR_URL: string; 6 | CALL_GRAPH_GENERATOR_CHECKSUM: string; 7 | } 8 | 9 | const config: Config = (snykConfig.loadConfig( 10 | path.join(__dirname, '..'), 11 | ) as unknown) as Config; 12 | 13 | export = config; 14 | -------------------------------------------------------------------------------- /lib/debug.ts: -------------------------------------------------------------------------------- 1 | import * as debugModule from 'debug'; 2 | 3 | // To enable debugging output, use `snyk -d` 4 | export function debug(s: string): void { 5 | if (process.env.DEBUG) { 6 | debugModule.enable(process.env.DEBUG); 7 | } 8 | return debugModule(`snyk-java-call-graph-builder`)(s); 9 | } 10 | -------------------------------------------------------------------------------- /lib/errors.ts: -------------------------------------------------------------------------------- 1 | export class CallGraphGenerationError extends Error { 2 | public innerError: Error; 3 | 4 | constructor(msg: string, innerError: Error) { 5 | super(msg); 6 | Object.setPrototypeOf(this, CallGraphGenerationError.prototype); 7 | this.innerError = innerError; 8 | } 9 | } 10 | 11 | export class ClassPathGenerationError extends Error { 12 | public readonly userMessage = 13 | "Could not determine the project's class path. Please contact our support or submit an issue at https://github.com/snyk/java-call-graph-builder/issues. Re-running the command with the `-d` flag will provide useful information for the support engineers."; 14 | 15 | public innerError: Error; 16 | 17 | constructor(innerError: Error) { 18 | super('Class path generation error'); 19 | Object.setPrototypeOf(this, ClassPathGenerationError.prototype); 20 | this.innerError = innerError; 21 | } 22 | } 23 | 24 | export class EmptyClassPathError extends Error { 25 | public readonly userMessage = 26 | 'The class path for the project is empty. Please contact our support or submit an issue at https://github.com/snyk/java-call-graph-builder/issues. Re-running the command with the `-d` flag will provide useful information for the support engineers.'; 27 | 28 | constructor(command: string) { 29 | super(`The command "${command}" returned an empty class path`); 30 | Object.setPrototypeOf(this, EmptyClassPathError.prototype); 31 | } 32 | } 33 | 34 | export class MissingTargetFolderError extends Error { 35 | public readonly userMessage: string; 36 | errorMessagePerPackageManager = { 37 | mvn: 38 | "Could not find the project's output directory. Please build your project and try again. " + 39 | 'The reachable vulnerabilities feature only supports the default Maven project layout, ' + 40 | "where the output directory is named 'target'.", 41 | gradle: 42 | "Could not find the project's target folder. Please compile your code and try again.", 43 | }; 44 | 45 | constructor(targetPath: string, packageManager: 'mvn' | 'gradle') { 46 | super(`Could not find the target folder starting in "${targetPath}"`); 47 | Object.setPrototypeOf(this, MissingTargetFolderError.prototype); 48 | 49 | this.userMessage = this.errorMessagePerPackageManager[packageManager]; 50 | } 51 | } 52 | 53 | export class SubprocessTimeoutError extends Error { 54 | public readonly userMessage = 55 | 'Scanning for reachable vulnerabilities took too long. Please use the --reachable-timeout flag to increase the timeout for finding reachable vulnerabilities.'; 56 | 57 | constructor(command: string, args: string, timeout: number) { 58 | super( 59 | `The command "${command} ${args}" timed out after ${timeout / 1000}s`, 60 | ); 61 | Object.setPrototypeOf(this, SubprocessTimeoutError.prototype); 62 | } 63 | } 64 | 65 | export class SubprocessError extends Error { 66 | constructor( 67 | command: string, 68 | args: string, 69 | exitCode: number, 70 | stdError?: string, 71 | ) { 72 | super( 73 | `The command "${command} ${args}" exited with code ${exitCode}${ 74 | stdError ? ', Standard Error Output: ' + stdError : '' 75 | }`, 76 | ); 77 | Object.setPrototypeOf(this, SubprocessError.prototype); 78 | } 79 | } 80 | 81 | export class MalformedModulesSpecError extends Error { 82 | constructor(modulesXml: string) { 83 | super(`Malformed modules XML: ${modulesXml}`); 84 | Object.setPrototypeOf(this, MalformedModulesSpecError.prototype); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib/fetch-snyk-java-call-graph-generator.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import * as needle from 'needle'; 4 | import * as ciInfo from 'ci-info'; 5 | import * as ProgressBar from 'progress'; 6 | import * as tempDir from 'temp-dir'; 7 | import * as crypto from 'crypto'; 8 | import { debug } from './debug'; 9 | 10 | import * as metrics from './metrics'; 11 | import ReadableStream = NodeJS.ReadableStream; 12 | 13 | import * as promisifedFs from './promisified-fs-glob'; 14 | 15 | export const JAR_NAME = 'java-call-graph-generator.jar'; 16 | 17 | const LOCAL_PATH = path.join(tempDir, 'call-graph-generator', JAR_NAME); 18 | 19 | function createProgressBar(total: number, name: string): ProgressBar { 20 | return new ProgressBar( 21 | `downloading ${name} [:bar] :rate/Kbps :percent :etas remaining`, 22 | { 23 | complete: '=', 24 | incomplete: '.', 25 | width: 20, 26 | total: total / 1000, 27 | clear: true, 28 | }, 29 | ); 30 | } 31 | 32 | async function downloadAnalyzer( 33 | url: string, 34 | localPath: string, 35 | expectedChecksum: string, 36 | ): Promise { 37 | return new Promise((resolve, reject) => { 38 | const fsStream = fs.createWriteStream(localPath + '.part'); 39 | try { 40 | let progressBar: ProgressBar; 41 | debug(`fetching java graph generator from ${url}`); 42 | const req = needle.get(url); 43 | let matchChecksum: Promise; 44 | let hasError = false; 45 | // TODO: Try pump (https://www.npmjs.com/package/pump) for more organised flow 46 | req 47 | .on('response', async (res) => { 48 | if (res.statusCode >= 400) { 49 | const err = new Error( 50 | 'Bad HTTP response for snyk-call-graph-generator download', 51 | ); 52 | // TODO: add custom error for status code => err.statusCode = res.statusCode; 53 | fsStream.destroy(); 54 | hasError = true; 55 | return reject(err); 56 | } 57 | matchChecksum = verifyChecksum(req, expectedChecksum); 58 | debug(`downloading ${JAR_NAME} ...`); 59 | if (!ciInfo.isCI) { 60 | const total = parseInt(res.headers['content-length'], 10); 61 | progressBar = createProgressBar(total, JAR_NAME); 62 | } 63 | }) 64 | .on('data', (chunk) => { 65 | if (progressBar) { 66 | progressBar.tick(chunk.length / 1000); 67 | } 68 | }) 69 | .on('error', (err) => { 70 | return reject(err); 71 | }) 72 | .pipe(fsStream) 73 | .on('error', (err) => { 74 | fsStream.destroy(); 75 | return reject(err); 76 | }) 77 | .on('finish', async () => { 78 | if (hasError) { 79 | await promisifedFs.unlink(localPath + '.part'); 80 | } else { 81 | if (!(await matchChecksum)) { 82 | return reject( 83 | new Error('Wrong checksum of downloaded call-graph-generator.'), 84 | ); 85 | } 86 | await promisifedFs.rename(localPath + '.part', localPath); 87 | resolve(localPath); 88 | } 89 | }); 90 | } catch (err) { 91 | reject(err); 92 | } 93 | }); 94 | } 95 | 96 | async function verifyChecksum( 97 | localPathStream: ReadableStream, 98 | expectedChecksum: string, 99 | ): Promise { 100 | return new Promise((resolve, reject) => { 101 | const hash = crypto.createHash('sha256'); 102 | localPathStream 103 | .on('error', reject) 104 | .on('data', (chunk) => { 105 | hash.update(chunk); 106 | }) 107 | .on('end', () => { 108 | resolve(hash.digest('hex') === expectedChecksum); 109 | }); 110 | }); 111 | } 112 | 113 | export async function fetch( 114 | url: string, 115 | expectedChecksum: string, 116 | ): Promise { 117 | const localPath = LOCAL_PATH; 118 | 119 | if (await promisifedFs.exists(localPath)) { 120 | if ( 121 | await verifyChecksum(fs.createReadStream(localPath), expectedChecksum) 122 | ) { 123 | return localPath; 124 | } 125 | debug(`new version of ${JAR_NAME} available`); 126 | } 127 | 128 | if (!(await promisifedFs.exists(path.dirname(localPath)))) { 129 | await promisifedFs.mkdir(path.dirname(localPath)); 130 | } 131 | 132 | return await metrics.timeIt('fetchCallGraphBuilder', () => 133 | downloadAnalyzer(url, localPath, expectedChecksum), 134 | ); 135 | } 136 | -------------------------------------------------------------------------------- /lib/gradle-wrapper.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | import { execute } from './sub-process'; 3 | import * as path from 'path'; 4 | import { EOL, platform } from 'os'; 5 | import { ClassPathGenerationError } from './errors'; 6 | import * as fs from 'fs'; 7 | import * as tmp from 'tmp'; 8 | 9 | export function getGradleCommandArgs( 10 | targetPath: string, 11 | initScript?: string, 12 | confAttrs?: string, 13 | ): string[] { 14 | // For binary releases, the original file would be in the binary build and inaccesible 15 | const originalPath = path.join(__dirname, ...'../bin/init.gradle'.split('/')); 16 | const tmpFilePath = tmp.fileSync().name; 17 | fs.copyFileSync(originalPath, tmpFilePath); 18 | 19 | const gradleArgs = ['printClasspath', '-I', tmpFilePath, '-q']; 20 | if (targetPath) { 21 | gradleArgs.push('-p', targetPath); 22 | } 23 | if (initScript) { 24 | gradleArgs.push('--init-script', initScript); 25 | } 26 | if (confAttrs) { 27 | const isWin = /^win/.test(platform()); 28 | const quot = isWin ? '"' : "'"; 29 | 30 | gradleArgs.push(`-PconfAttrs=${quot}${confAttrs}${quot}`); 31 | } 32 | 33 | return gradleArgs; 34 | } 35 | 36 | export async function getClassPathFromGradle( 37 | targetPath: string, 38 | gradlePath: string, 39 | initScript?: string, 40 | confAttrs?: string, 41 | ): Promise { 42 | const args = getGradleCommandArgs(targetPath, initScript, confAttrs); 43 | try { 44 | const output = await execute(gradlePath, args, { cwd: targetPath }); 45 | const lines = output.trim().split(EOL); 46 | const lastLine = lines[lines.length - 1]; 47 | 48 | return lastLine.trim(); 49 | } catch (e) { 50 | console.log(e); 51 | throw new ClassPathGenerationError(e); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | import { getClassPathFromMvn } from './mvn-wrapper-legacy'; 3 | import { getClassPathFromGradle } from './gradle-wrapper'; 4 | import { getCallGraph } from './java-wrapper'; 5 | import { Graph } from '@snyk/graphlib'; 6 | import { timeIt, getMetrics, Metrics } from './metrics'; 7 | import { CallGraphGenerationError, MissingTargetFolderError } from './errors'; 8 | import { glob } from './promisified-fs-glob'; 9 | import * as path from 'path'; 10 | import { makeMavenProject } from './mvn-wrapper'; 11 | import { debug } from './debug'; 12 | import * as tmp from 'tmp'; 13 | 14 | tmp.setGracefulCleanup(); 15 | 16 | export async function getCallGraphMvnLegacy( 17 | targetPath: string, 18 | timeout?: number, 19 | customMavenArgs?: string[], 20 | ): Promise { 21 | try { 22 | const [classPath, targets] = await Promise.all([ 23 | timeIt('getMvnClassPath', () => 24 | getClassPathFromMvn(targetPath, customMavenArgs), 25 | ), 26 | timeIt('getEntrypoints', () => findBuildDirs(targetPath, 'mvn')), 27 | ]); 28 | 29 | return await timeIt('getCallGraph', () => 30 | getCallGraph(classPath, targetPath, targets, timeout), 31 | ); 32 | } catch (e) { 33 | throw new CallGraphGenerationError( 34 | e.userMessage || 35 | 'Failed to scan for reachable vulnerabilities. Please contact our support or submit an issue at https://github.com/snyk/java-call-graph-builder/issues. Re-running the command with the `-d` flag will provide useful information for the support engineers.', 36 | e, 37 | ); 38 | } 39 | } 40 | 41 | export async function getCallGraphMvn( 42 | targetPath: string, 43 | timeout?: number, 44 | customMavenArgs?: string[], 45 | ): Promise { 46 | try { 47 | const project = await makeMavenProject(targetPath, customMavenArgs); 48 | const classPath = project.getClassPath(); 49 | const buildDirectories = await Promise.all( 50 | project.modules.map((m) => m.buildDirectory), 51 | ); 52 | 53 | return await timeIt('getCallGraph', () => 54 | getCallGraph(classPath, targetPath, buildDirectories, timeout), 55 | ); 56 | } catch (e) { 57 | debug( 58 | `Failed to get the call graph for the Maven project in: ${targetPath}. ' + 59 | 'Falling back to the legacy method.`, 60 | ); 61 | return getCallGraphMvnLegacy(targetPath, timeout, customMavenArgs); 62 | } 63 | } 64 | 65 | export async function getCallGraphGradle( 66 | targetPath: string, 67 | gradlePath = 'gradle', 68 | initScript?: string, 69 | confAttrs?: string, 70 | timeout?: number, 71 | ): Promise { 72 | const [classPath, targets] = await Promise.all([ 73 | timeIt('getGradleClassPath', () => 74 | getClassPathFromGradle(targetPath, gradlePath, initScript, confAttrs), 75 | ), 76 | timeIt('getEntrypoints', () => findBuildDirs(targetPath, 'gradle')), 77 | ]); 78 | 79 | debug(`got class path: ${classPath}`); 80 | debug(`got targets: ${targets}`); 81 | 82 | return await timeIt('getCallGraph', () => 83 | getCallGraph(classPath, targetPath, targets, timeout), 84 | ); 85 | } 86 | 87 | export function runtimeMetrics(): Metrics { 88 | return getMetrics(); 89 | } 90 | 91 | export async function findBuildDirs( 92 | targetPath: string, 93 | packageManager: 'mvn' | 'gradle', 94 | ): Promise { 95 | const targetFoldersByPackageManager = { 96 | mvn: 'target', 97 | gradle: 'build', 98 | }; 99 | const targetDirs = await glob( 100 | path.join( 101 | targetPath, 102 | `**/${targetFoldersByPackageManager[packageManager]}`, 103 | ), 104 | ); 105 | if (!targetDirs.length) { 106 | throw new MissingTargetFolderError(targetPath, packageManager); 107 | } 108 | 109 | return targetDirs; 110 | } 111 | -------------------------------------------------------------------------------- /lib/java-wrapper.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | 3 | import * as jszip from 'jszip'; 4 | import { Graph } from '@snyk/graphlib'; 5 | import * as path from 'path'; 6 | import * as config from './config'; 7 | 8 | import { execute } from './sub-process'; 9 | import { fetch } from './fetch-snyk-java-call-graph-generator'; 10 | import { buildCallGraph } from './call-graph'; 11 | import * as promisifedFs from './promisified-fs-glob'; 12 | import { readFile } from './promisified-fs-glob'; 13 | import { toFQclassName } from './class-parsing'; 14 | import { timeIt } from './metrics'; 15 | import * as tempDir from 'temp-dir'; 16 | 17 | export function getCallGraphGenCommandArgs( 18 | classPath: string, 19 | jarPath: string, 20 | targets: string[], 21 | ): string[] { 22 | return [ 23 | '-cp', 24 | jarPath, 25 | 'io.snyk.callgraph.app.App', 26 | '--application-classpath-file', 27 | classPath, 28 | '--dirs-to-get-entrypoints', 29 | targets.join(','), 30 | ]; 31 | } 32 | 33 | export async function getClassPerJarMapping( 34 | classPath: string, 35 | ): Promise<{ [index: string]: string }> { 36 | const classPerJarMapping: { [index: string]: string } = {}; 37 | for (const classPathItem of classPath.split(path.delimiter)) { 38 | // classpath can also contain local directories with classes - we don't need them for package mapping 39 | if (!classPathItem.endsWith('.jar')) { 40 | continue; 41 | } 42 | const jarFileContent = await readFile(classPathItem); 43 | const jarContent = await jszip.loadAsync(jarFileContent); 44 | for (const classFile of Object.keys(jarContent.files).filter((name) => 45 | name.endsWith('.class'), 46 | )) { 47 | const className = toFQclassName(classFile.replace('.class', '')); // removing .class from name 48 | classPerJarMapping[className] = classPathItem; 49 | } 50 | } 51 | return classPerJarMapping; 52 | } 53 | 54 | export async function getCallGraph( 55 | classPath: string, 56 | targetPath: string, 57 | targets: string[], 58 | timeout?: number, 59 | ): Promise { 60 | const [jarPath, { tmpDir, classPathFile }] = await Promise.all([ 61 | fetch( 62 | config.CALL_GRAPH_GENERATOR_URL, 63 | config.CALL_GRAPH_GENERATOR_CHECKSUM, 64 | ), 65 | writeClassPathToTempDir(classPath), 66 | ]); 67 | 68 | const callgraphGenCommandArgs = getCallGraphGenCommandArgs( 69 | classPathFile, 70 | jarPath, 71 | targets, 72 | ); 73 | 74 | try { 75 | const [javaOutput, classPerJarMapping] = await Promise.all([ 76 | timeIt('generateCallGraph', () => 77 | execute('java', callgraphGenCommandArgs, { 78 | cwd: targetPath, 79 | timeout, 80 | }), 81 | ), 82 | timeIt('mapClassesPerJar', () => getClassPerJarMapping(classPath)), 83 | ]); 84 | 85 | return buildCallGraph(javaOutput, classPerJarMapping); 86 | } finally { 87 | // Fire and forget - we don't have to wait for a deletion of a temporary file 88 | cleanupTempDir(classPathFile, tmpDir); 89 | } 90 | } 91 | 92 | async function writeClassPathToTempDir(classPath) { 93 | const tmpDir = await promisifedFs.mkdtemp( 94 | path.join(tempDir, 'call-graph-generator'), 95 | ); 96 | const classPathFile = path.join(tmpDir, 'callgraph-classpath'); 97 | await promisifedFs.writeFile(classPathFile, classPath); 98 | 99 | return { tmpDir, classPathFile }; 100 | } 101 | 102 | async function cleanupTempDir(classPathFile: string, tmpDir: string) { 103 | try { 104 | await promisifedFs.unlink(classPathFile); 105 | await promisifedFs.rmdir(tmpDir); 106 | } catch { 107 | // we couldn't delete temporary data in temporary folder, no big deal 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/metrics.ts: -------------------------------------------------------------------------------- 1 | export { Metrics, timeIt, getMetrics }; 2 | 3 | interface Metrics { 4 | fetchCallGraphBuilder?: number; 5 | getMvnClassPath?: number; 6 | getGradleClassPath?: number; 7 | getEntrypoints: number; 8 | generateCallGraph: number; 9 | mapClassesPerJar: number; 10 | getCallGraph: number; 11 | } 12 | 13 | const metricsState: { 14 | [metric in keyof Metrics]: { seconds: number; nanoseconds: number }; 15 | } = { 16 | getEntrypoints: { seconds: 0, nanoseconds: 0 }, 17 | generateCallGraph: { seconds: 0, nanoseconds: 0 }, 18 | mapClassesPerJar: { seconds: 0, nanoseconds: 0 }, 19 | getCallGraph: { seconds: 0, nanoseconds: 0 }, 20 | }; 21 | 22 | function start(metric: keyof Metrics) { 23 | const [secs, nsecs] = process.hrtime(); 24 | metricsState[metric] = { seconds: secs, nanoseconds: nsecs }; 25 | } 26 | 27 | function stop(metric: keyof Metrics) { 28 | const { seconds, nanoseconds } = metricsState[metric] || { 29 | seconds: 0, 30 | nanoseconds: 0, 31 | }; 32 | const [secs, nsecs] = process.hrtime([seconds, nanoseconds]); 33 | metricsState[metric] = { seconds: secs, nanoseconds: nsecs }; 34 | } 35 | 36 | function getMetrics(): Metrics { 37 | const metrics = {} as Metrics; 38 | 39 | for (const [metric, value] of Object.entries(metricsState)) { 40 | if (!value) { 41 | continue; 42 | } 43 | 44 | const { seconds, nanoseconds } = value; 45 | metrics[metric] = seconds + nanoseconds / 1e9; 46 | } 47 | 48 | return metrics; 49 | } 50 | 51 | async function timeIt( 52 | metric: keyof Metrics, 53 | fn: () => Promise, 54 | ): Promise { 55 | start(metric); 56 | const x = await fn(); 57 | stop(metric); 58 | return x; 59 | } 60 | -------------------------------------------------------------------------------- /lib/mvn-wrapper-legacy.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | import { execute } from './sub-process'; 3 | import { ClassPathGenerationError, EmptyClassPathError } from './errors'; 4 | import * as path from 'path'; 5 | import * as os from 'os'; 6 | 7 | export function getMvnCommandArgsForMvnExec(targetPath: string): string[] { 8 | return process.platform === 'win32' 9 | ? [ 10 | '-q', 11 | 'exec:exec', 12 | '-Dexec.classpathScope="compile"', 13 | '-Dexec.executable="cmd"', 14 | '-Dexec.args="/c echo %classpath"', 15 | '-f', 16 | targetPath, 17 | ] 18 | : [ 19 | '-q', 20 | 'exec:exec', 21 | '-Dexec.classpathScope="compile"', 22 | '-Dexec.executable="echo"', 23 | '-Dexec.args="%classpath"', 24 | '-f', 25 | targetPath, 26 | ]; 27 | } 28 | 29 | function getMvnCommandArgsForDependencyPlugin(targetPath: string): string[] { 30 | return ['dependency:build-classpath', '-f', targetPath]; 31 | } 32 | 33 | export function parseMvnDependencyPluginCommandOutput( 34 | mvnCommandOutput: string, 35 | ): string[] { 36 | const outputLines = mvnCommandOutput.split(os.EOL); 37 | const uniqueClassPaths = new Set(); 38 | let startIndex = 0; 39 | let i = outputLines.indexOf('[INFO] Dependencies classpath:', startIndex); 40 | while (i > -1) { 41 | if (outputLines[i + 1] !== '') { 42 | uniqueClassPaths.add(outputLines[i + 1]); 43 | } 44 | startIndex = i + 2; 45 | i = outputLines.indexOf('[INFO] Dependencies classpath:', startIndex); 46 | } 47 | return Array.from(uniqueClassPaths.values()).sort(); 48 | } 49 | 50 | export function parseMvnExecCommandOutput(mvnCommandOutput: string): string[] { 51 | return mvnCommandOutput 52 | .trim() 53 | .split(os.EOL) 54 | .sort(); 55 | } 56 | 57 | export function mergeMvnClassPaths(classPaths: string[]): string { 58 | // this magic joins all items in array with :, splits result by : again 59 | // makes Set (to uniq items), create Array from it and join it by : to have 60 | // proper path like format 61 | return Array.from( 62 | new Set(classPaths.join(path.delimiter).split(path.delimiter)), 63 | ) 64 | .sort() 65 | .join(path.delimiter); 66 | } 67 | 68 | export async function getClassPathFromMvn( 69 | targetPath: string, 70 | customMavenArgs: string[] = [], 71 | ): Promise { 72 | let classPaths: string[] = []; 73 | let args: string[] = []; 74 | try { 75 | try { 76 | // there are two ways of getting classpath - either from maven plugin or by exec command 77 | // try `mvn exec` for classpath 78 | args = getMvnCommandArgsForMvnExec(targetPath).concat(customMavenArgs); 79 | const output = await execute('mvn', args, { cwd: targetPath }); 80 | classPaths = parseMvnExecCommandOutput(output); 81 | } catch (e) { 82 | // if it fails, try mvn dependency:build-classpath 83 | // TODO send error message for further analysis 84 | args = getMvnCommandArgsForDependencyPlugin(targetPath).concat( 85 | customMavenArgs, 86 | ); 87 | const output = await execute('mvn', args, { cwd: targetPath }); 88 | classPaths = parseMvnDependencyPluginCommandOutput(output); 89 | } 90 | } catch (e) { 91 | throw new ClassPathGenerationError(e); 92 | } 93 | if (classPaths.length === 0) { 94 | throw new EmptyClassPathError(`mvn ${args.join(' ')}`); 95 | } 96 | return mergeMvnClassPaths(classPaths); 97 | } 98 | -------------------------------------------------------------------------------- /lib/mvn-wrapper.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | import * as path from 'path'; 3 | import * as fs from 'fs'; 4 | import * as xmlJs from 'xml-js'; 5 | import { ClassPath } from './classpath'; 6 | import * as tmp from 'tmp'; 7 | import { execute } from './sub-process'; 8 | import { MalformedModulesSpecError } from './errors'; 9 | import { timeIt } from './metrics'; 10 | import { debug } from './debug'; 11 | 12 | // Low level helper functions 13 | 14 | export async function withOutputToTemporaryFile( 15 | f: (fileName: string) => Promise, 16 | ): Promise { 17 | // NOTE(alexmu): We have to do this little dance with output written to files 18 | // because that seems to be the only way to get the output without having to 19 | // parse maven logs 20 | const file = tmp.fileSync({ discardDescriptor: true }); 21 | try { 22 | await f(file.name); 23 | } catch (e) { 24 | debug(`Failed to execute command with temporary file: ${e}`); 25 | throw e; 26 | } 27 | 28 | try { 29 | return fs.readFileSync(file.name, 'utf8'); 30 | } catch (e) { 31 | debug(`Failed to read temporary file: ${e}`); 32 | throw e; 33 | } 34 | } 35 | 36 | function runCommand(projectDirectory: string, args: string[]): Promise { 37 | return execute('mvn', args.concat(['-f', projectDirectory]), { 38 | cwd: projectDirectory, 39 | }); 40 | } 41 | 42 | // Domain specific helpers 43 | 44 | async function evaluateExpression( 45 | projectDirectory: string, 46 | expression: string, 47 | customMavenArgs: string[] = [], 48 | ): Promise { 49 | return await withOutputToTemporaryFile(async (outputFile) => { 50 | await runCommand(projectDirectory, [ 51 | 'help:evaluate', 52 | `-Dexpression="${expression}"`, 53 | `-Doutput=${outputFile}`, 54 | ...customMavenArgs, 55 | ]); 56 | }); 57 | } 58 | 59 | export async function getBuildDir( 60 | baseDir: string, 61 | customMavenArgs?: string[], 62 | ): Promise { 63 | return await evaluateExpression( 64 | baseDir, 65 | 'project.build.directory', 66 | customMavenArgs, 67 | ); 68 | } 69 | 70 | export async function getOutputDir( 71 | baseDir: string, 72 | customMavenArgs?: string[], 73 | ): Promise { 74 | return await evaluateExpression( 75 | baseDir, 76 | 'project.build.outputDirectory', 77 | customMavenArgs, 78 | ); 79 | } 80 | 81 | export async function getDepsClassPath( 82 | baseDir: string, 83 | customMavenArgs: string[] = [], 84 | ): Promise { 85 | const classPath = await withOutputToTemporaryFile(async (outputFile) => { 86 | await runCommand(baseDir, [ 87 | 'dependency:build-classpath', 88 | `-Dmdep.outputFile=${outputFile}`, 89 | ...customMavenArgs, 90 | ]); 91 | }); 92 | return new ClassPath(classPath); 93 | } 94 | 95 | export function parseModuleNames(modulesXml: string): string[] { 96 | const modulesSpec = xmlJs.xml2js(modulesXml, { compact: true }); 97 | if ('strings' in modulesSpec && 'string' in modulesSpec['strings']) { 98 | debug(`Found 'strings' in the modules XML`); 99 | return modulesSpec['strings']['string'].map((s) => s['_text']); 100 | } else if ('modules' in modulesSpec) { 101 | debug(`Empty modules XML`); 102 | return []; 103 | } else { 104 | throw new MalformedModulesSpecError(modulesXml); 105 | } 106 | } 107 | 108 | // Maven model 109 | 110 | export class MavenModule { 111 | public readonly baseDirectory: string; 112 | public readonly buildDirectory: string; 113 | public readonly outputDirectory: string; 114 | public readonly dependenciesClassPath: ClassPath; 115 | 116 | constructor( 117 | baseDir: string, 118 | buildDirectory: string, 119 | outputDirectory: string, 120 | dependenciesClassPath: ClassPath, 121 | ) { 122 | if (buildDirectory?.length === 0) { 123 | throw new Error(`Empty build directory for the project in: ${baseDir}`); 124 | } 125 | if (outputDirectory?.length === 0) { 126 | throw new Error(`Empty output directory for the project in: ${baseDir}`); 127 | } 128 | if (dependenciesClassPath?.isEmpty()) { 129 | throw new Error(`Empty dependencies for the project in: ${baseDir}`); 130 | } 131 | 132 | this.baseDirectory = baseDir; 133 | this.buildDirectory = buildDirectory; 134 | this.outputDirectory = outputDirectory; 135 | this.dependenciesClassPath = dependenciesClassPath; 136 | } 137 | 138 | public getClassPath(): ClassPath { 139 | debug(`Dependencies class path: ${this.dependenciesClassPath}`); 140 | debug(`Output directory: ${this.outputDirectory}`); 141 | return this.dependenciesClassPath.concat( 142 | new ClassPath(this.outputDirectory), 143 | ); 144 | } 145 | } 146 | 147 | export class MavenProject { 148 | public readonly baseDir: string; 149 | public readonly modules: MavenModule[]; 150 | 151 | constructor(baseDir: string, modules: MavenModule[]) { 152 | if (modules?.length === 0) { 153 | throw new Error(`Empty module list for the project in: ${baseDir}`); 154 | } 155 | this.baseDir = baseDir; 156 | this.modules = modules; 157 | } 158 | 159 | public getClassPath(): string { 160 | const classPaths = this.modules.map((module) => module.getClassPath()); 161 | const cp = classPaths.reduce((cp1, cp2) => cp1.concat(cp2)); 162 | debug(`Project class path: ${cp}`); 163 | return cp.toString(); 164 | } 165 | } 166 | 167 | // Factories that deal with the low level details 168 | 169 | export async function makeMavenModule( 170 | baseDir: string, 171 | args?: string[], 172 | ): Promise { 173 | const buildDir = await getBuildDir(baseDir, args); 174 | const outputDir = await getOutputDir(baseDir, args); 175 | const depsClassPath = await timeIt('getMvnClassPath', async () => { 176 | return await getDepsClassPath(baseDir, args); 177 | }); 178 | return new MavenModule(baseDir, buildDir, outputDir, depsClassPath); 179 | } 180 | 181 | export async function makeMavenProject( 182 | baseDir: string, 183 | customMavenArgs?: string[], 184 | ): Promise { 185 | const modulesXml = await evaluateExpression( 186 | baseDir, 187 | 'project.modules', 188 | customMavenArgs, 189 | ); 190 | const moduleNames = parseModuleNames(modulesXml); 191 | const modules = [await makeMavenModule(baseDir, customMavenArgs)]; 192 | const submodules = await Promise.all( 193 | moduleNames.map((name) => makeMavenModule(path.join(baseDir, name))), 194 | ); 195 | modules.push(...submodules); 196 | const validModules = modules.filter((module) => 197 | fs.existsSync(module.buildDirectory), 198 | ); 199 | return new MavenProject(baseDir, validModules); 200 | } 201 | -------------------------------------------------------------------------------- /lib/promisified-fs-glob.ts: -------------------------------------------------------------------------------- 1 | import { promisify } from 'util'; 2 | import * as fs from 'fs'; 3 | import * as globOrig from 'glob'; 4 | 5 | export const exists = promisify(fs.exists); 6 | export const rename = promisify(fs.rename); 7 | export const unlink = promisify(fs.unlink); 8 | export const mkdir = promisify(fs.mkdir); 9 | export const mkdtemp = promisify(fs.mkdtemp); 10 | export const readFile = promisify(fs.readFile); 11 | export const writeFile = promisify(fs.writeFile); 12 | export const rmdir = promisify(fs.rmdir); 13 | export const glob = promisify(globOrig); 14 | -------------------------------------------------------------------------------- /lib/sub-process.ts: -------------------------------------------------------------------------------- 1 | import * as childProcess from 'child_process'; 2 | import { debug } from './debug'; 3 | import { SubprocessError, SubprocessTimeoutError } from './errors'; 4 | 5 | export function execute( 6 | command: string, 7 | args: string[], 8 | options?: { 9 | cwd?: string; 10 | timeout?: number; 11 | }, 12 | ): Promise { 13 | const spawnOptions: childProcess.SpawnOptions = { shell: true }; 14 | if (options && options.cwd) { 15 | spawnOptions.cwd = options.cwd; 16 | } 17 | 18 | return new Promise((resolve, reject) => { 19 | let stdout = ''; 20 | let stderr = ''; 21 | 22 | debug(`executing command: "${command} ${args.join(' ')}"`); 23 | const proc = childProcess.spawn(command, args, spawnOptions); 24 | 25 | let timerId: NodeJS.Timer | null = null; 26 | if (options?.timeout) { 27 | timerId = setTimeout(() => { 28 | proc.kill(); 29 | const err = new SubprocessTimeoutError( 30 | command, 31 | args.join(' '), 32 | options.timeout || 0, 33 | ); 34 | debug(err.message); 35 | reject(err); 36 | }, options.timeout); 37 | } 38 | 39 | proc.stdout.on('data', (data: Buffer) => { 40 | stdout = stdout + data; 41 | }); 42 | proc.stderr.on('data', (data: Buffer) => { 43 | stderr = stderr + data; 44 | }); 45 | 46 | proc.on('close', (code: number) => { 47 | if (timerId !== null) { 48 | clearTimeout(timerId); 49 | } 50 | if (code !== 0) { 51 | const trimmedStackTrace = stderr 52 | .replace(/\t/g, '') 53 | .split('\n') 54 | .slice(0, 5) 55 | .join(', '); 56 | const err = new SubprocessError( 57 | command, 58 | args.join(' '), 59 | code, 60 | trimmedStackTrace, 61 | ); 62 | debug(err.message); 63 | return reject(err); 64 | } 65 | resolve(stdout); 66 | }); 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@snyk/java-call-graph-builder", 3 | "description": "Tool for building a call graph for JVM ecosystem (Maven, Gradle...)", 4 | "main": "dist/index.js", 5 | "scripts": { 6 | "format:check": "prettier --check '{lib,test}/**/*.{js,ts,json,yml}'", 7 | "format": "prettier --write '{lib,test}/**/*.{js,ts,json,yml}'", 8 | "lint": "npm run format:check && npm run lint:eslint", 9 | "lint:eslint": "eslint --color --cache 'lib/**/*.{js,ts}'", 10 | "test": "npm run lint && npm run test:unit && npm run test:integration", 11 | "test:unit": "jest test/lib", 12 | "test:integration": "jest test/integration --runInBand", 13 | "test:coverage": "npm run test:unit -- --coverage", 14 | "test:watch": "tsc-watch --onSuccess 'npm run test:unit'", 15 | "build": "tsc", 16 | "build-watch": "tsc -w", 17 | "prepare": "npm run build" 18 | }, 19 | "types": "./dist/index.d.ts", 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/snyk/java-call-graph-builder" 23 | }, 24 | "author": "snyk.io", 25 | "license": "Apache-2.0", 26 | "engines": { 27 | "node": ">=8" 28 | }, 29 | "files": [ 30 | "bin", 31 | "dist", 32 | "config.default.json" 33 | ], 34 | "homepage": "https://github.com/snyk/java-call-graph-builder#readme", 35 | "dependencies": { 36 | "@snyk/graphlib": "2.1.9-patch.3", 37 | "ci-info": "^2.0.0", 38 | "debug": "^4.1.1", 39 | "glob": "^7.1.6", 40 | "jszip": "^3.7.0", 41 | "needle": "^2.3.3", 42 | "progress": "^2.0.3", 43 | "snyk-config": "^4.0.0-rc.2", 44 | "source-map-support": "^0.5.7", 45 | "temp-dir": "^2.0.0", 46 | "tmp": "^0.2.1", 47 | "tslib": "^1.9.3", 48 | "xml-js": "^1.6.11" 49 | }, 50 | "devDependencies": { 51 | "@types/ci-info": "^2.0.0", 52 | "@types/debug": "^4.1.5", 53 | "@types/glob": "^7.1.1", 54 | "@types/jest": "^24.9.1", 55 | "@types/jszip": "^3.1.7", 56 | "@types/needle": "^2.0.4", 57 | "@types/nock": "^11.1.0", 58 | "@types/node": "^8.10.59", 59 | "@types/progress": "^2.0.3", 60 | "@typescript-eslint/eslint-plugin": "2.18.0", 61 | "@typescript-eslint/parser": "^2.0.0", 62 | "eslint": "^6.8.0", 63 | "eslint-config-prettier": "^6.1.0", 64 | "jest": "^24.9.0", 65 | "nock": "^11.9.1", 66 | "prettier": "^1.18.2", 67 | "ts-jest": "^24.0.2", 68 | "ts-node": "7.0.0", 69 | "tsc-watch": "^2.2.1", 70 | "typescript": "^3.8.3" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc"], 3 | "overrides": [ 4 | { 5 | "files": ["**/*.test.js"], 6 | "plugins": ["mocha"], 7 | "env": { 8 | "mocha": true 9 | } 10 | }, 11 | { 12 | "files": ["**/*.test.ts"], 13 | "parserOptions": { 14 | "project": "./tsconfig.json" 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/Priority.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/Priority.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/Todo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/Todo.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/domain/User.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/api/TodoRepository.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/api/TodoRepository.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/api/UserRepository.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/api/UserRepository.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/impl/TodoRepositoryImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/impl/TodoRepositoryImpl.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/impl/UserRepositoryImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/repository/impl/UserRepositoryImpl.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/api/TodoService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/api/TodoService.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/api/UserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/api/UserService.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/impl/TodoServiceImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/impl/TodoServiceImpl.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/impl/UserServiceImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/classes/io/github/todolist/core/service/impl/UserServiceImpl.class -------------------------------------------------------------------------------- /test/fixtures/example-java-project/target/todolist-core-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/example-java-project/target/todolist-core-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /test/fixtures/java-goof-expected-jars.json: -------------------------------------------------------------------------------- 1 | { 2 | "com.opensymphony.xwork2.ActionSupport": "xwork-core-2.3.20.jar", 3 | "java.lang.String": "java.base", 4 | "com.opensymphony.xwork2.ActionContext": "xwork-core-2.3.20.jar", 5 | "com.opensymphony.xwork2.Preparable": "xwork-core-2.3.20.jar", 6 | "io.github.benas.todolist.web.common.util.TodoListUtils": ".", 7 | "io.github.todolist.core.domain.User": ".", 8 | "io.github.todolist.core.service.api.TodoService": ".", 9 | "io.github.todolist.core.service.api.UserService": ".", 10 | "java.lang.Exception": "java.base", 11 | "java.lang.Object": "java.base", 12 | "java.util.Map": "java.base", 13 | "javax.validation.Validation": "javaee-web-api-6.0.jar", 14 | "javax.validation.Validator": "javaee-web-api-6.0.jar", 15 | "javax.validation.ValidatorFactory": "javaee-web-api-6.0.jar", 16 | "com.opensymphony.xwork2.Action": "xwork-core-2.3.20.jar", 17 | "io.github.benas.todolist.web.action.BaseAction": ".", 18 | "io.github.todolist.core.domain.Todo": ".", 19 | "java.lang.Long": "java.base", 20 | "java.util.List": "java.base", 21 | "io.github.todolist.core.domain.Priority": ".", 22 | "java.io.File": "java.base", 23 | "java.io.PrintStream": "java.base", 24 | "java.lang.System": "java.base", 25 | "java.text.MessageFormat": "java.base", 26 | "java.util.Date": "java.base", 27 | "org.zeroturnaround.zip.ZipUtil": "zt-zip-1.12.jar", 28 | "com.opensymphony.xwork2.util.logging.Logger": "xwork-core-2.3.20.jar", 29 | "com.opensymphony.xwork2.util.logging.LoggerFactory": "xwork-core-2.3.20.jar", 30 | "io.github.benas.todolist.web.common.form.ChangePasswordForm": ".", 31 | "io.github.benas.todolist.web.common.form.RegistrationForm": ".", 32 | "java.lang.Class": "java.base", 33 | "java.lang.IllegalStateException": "java.base", 34 | "java.lang.Throwable": "java.base", 35 | "java.util.Iterator": "java.base", 36 | "java.util.Set": "java.base", 37 | "javax.validation.ConstraintViolation": "javaee-web-api-6.0.jar", 38 | "org.apache.struts2.dispatcher.SessionMap": "struts2-core-2.3.20.jar", 39 | "io.github.benas.todolist.web.common.form.LoginForm": ".", 40 | "javax.validation.constraints.Size": "javaee-web-api-6.0.jar", 41 | "org.hibernate.validator.constraints.NotEmpty": "hibernate-validator-4.3.1.Final.jar", 42 | "org.hibernate.validator.constraints.Email": "hibernate-validator-4.3.1.Final.jar", 43 | "java.io.IOException": "java.base", 44 | "java.io.StringWriter": "java.base", 45 | "java.io.Writer": "java.base", 46 | "java.lang.CharSequence": "java.base", 47 | "java.lang.StringBuilder": "java.base", 48 | "java.util.regex.Matcher": "java.base", 49 | "java.util.regex.Pattern": "java.base", 50 | "javax.servlet.jsp.JspContext": "javaee-web-api-6.0.jar", 51 | "javax.servlet.jsp.JspException": "javaee-web-api-6.0.jar", 52 | "javax.servlet.jsp.JspWriter": "javaee-web-api-6.0.jar", 53 | "javax.servlet.jsp.tagext.JspFragment": "javaee-web-api-6.0.jar", 54 | "javax.servlet.jsp.tagext.SimpleTagSupport": "javaee-web-api-6.0.jar", 55 | "java.lang.NoSuchFieldError": "java.base", 56 | "com.opensymphony.xwork2.ActionInvocation": "xwork-core-2.3.20.jar", 57 | "com.opensymphony.xwork2.interceptor.AbstractInterceptor": "xwork-core-2.3.20.jar", 58 | "org.junit.Assert": "junit-4.12.jar", 59 | "org.junit.Test": "junit-4.12.jar", 60 | "org.junit.runner.RunWith": "junit-4.12.jar", 61 | "org.springframework.beans.factory.annotation.Autowired": "spring-beans-3.2.6.RELEASE.jar", 62 | "org.springframework.test.context.ContextConfiguration": "spring-test-3.2.6.RELEASE.jar", 63 | "java.lang.Enum": "java.base", 64 | "java.io.BufferedReader": "java.base", 65 | "java.io.BufferedWriter": "java.base", 66 | "java.io.FileWriter": "java.base", 67 | "java.io.InputStream": "java.base", 68 | "java.io.InputStreamReader": "java.base", 69 | "java.io.Reader": "java.base", 70 | "java.io.Serializable": "java.base", 71 | "java.lang.Process": "java.base", 72 | "java.lang.Runtime": "java.base", 73 | "javax.persistence.Column": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 74 | "javax.persistence.Entity": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 75 | "javax.persistence.Enumerated": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 76 | "javax.persistence.GeneratedValue": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 77 | "javax.persistence.Id": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 78 | "javax.persistence.NamedQueries": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 79 | "javax.persistence.Temporal": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 80 | "io.github.todolist.core.repository.api.TodoRepository": ".", 81 | "javax.persistence.EntityManager": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 82 | "javax.persistence.PersistenceContext": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 83 | "javax.persistence.TypedQuery": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 84 | "org.springframework.stereotype.Repository": "spring-context-3.2.6.RELEASE.jar", 85 | "io.github.todolist.core.repository.api.UserRepository": ".", 86 | "javax.persistence.Query": "hibernate-jpa-2.1-api-1.0.0.Final.jar", 87 | "org.springframework.stereotype.Service": "spring-context-3.2.6.RELEASE.jar", 88 | "org.springframework.transaction.annotation.Transactional": "spring-tx-3.2.6.RELEASE.jar" 89 | } 90 | -------------------------------------------------------------------------------- /test/fixtures/java-goof-mvn-dependency-plugin-output-line-feed-and-carriage-return.txt: -------------------------------------------------------------------------------- 1 | [INFO] Scanning for projects... 2 | [INFO] ------------------------------------------------------------------------ 3 | [INFO] Reactor Build Order: 4 | [INFO] 5 | [INFO] Todolist MVC parent module [pom] 6 | [INFO] todolist-core [jar] 7 | [INFO] todolist-web-common [jar] 8 | [INFO] todolist-web-struts Maven Webapp [war] 9 | [INFO] 10 | [INFO] --------------------< io.github.snyk:todolist-mvc >--------------------- 11 | [INFO] Building Todolist MVC parent module 1.0-SNAPSHOT [1/4] 12 | [INFO] --------------------------------[ pom ]--------------------------------- 13 | [INFO] 14 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-mvc --- 15 | [INFO] No dependencies found. 16 | [INFO] Dependencies classpath: 17 | 18 | [INFO] 19 | [INFO] --------------------< io.github.snyk:todolist-core >-------------------- 20 | [INFO] Building todolist-core 1.0-SNAPSHOT [2/4] 21 | [INFO] --------------------------------[ jar ]--------------------------------- 22 | [INFO] 23 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-core --- 24 | [INFO] Dependencies classpath: 25 | /Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar;/Users/mila/.m2/repository/junit/junit/4.12/junit-4.12.jar;/Users/mila/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar;/Users/mila/.m2/repository/org/springframework/spring-test/3.2.6.RELEASE/spring-test-3.2.6.RELEASE.jar 26 | [INFO] 27 | [INFO] -----------------< io.github.snyk:todolist-web-common >----------------- 28 | [INFO] Building todolist-web-common 1.0-SNAPSHOT [3/4] 29 | [INFO] --------------------------------[ jar ]--------------------------------- 30 | [INFO] 31 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-web-common --- 32 | [INFO] Dependencies classpath: 33 | /Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar;/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar;/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar;/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar 34 | [INFO] 35 | [INFO] -----------------< io.github.snyk:todolist-web-struts >----------------- 36 | [INFO] Building todolist-web-struts Maven Webapp 1.0-SNAPSHOT [4/4] 37 | [INFO] --------------------------------[ war ]--------------------------------- 38 | [INFO] 39 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-web-struts --- 40 | [INFO] Dependencies classpath: 41 | /Users/mila/.m2/repository/io/github/snyk/todolist-web-common/1.0-SNAPSHOT/todolist-web-common-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar;/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar;/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar;/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar;/Users/mila/.m2/repository/org/springframework/spring-web/3.2.6.RELEASE/spring-web-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/apache/struts/struts2-core/2.3.20/struts2-core-2.3.20.jar;/Users/mila/.m2/repository/org/apache/struts/xwork/xwork-core/2.3.20/xwork-core-2.3.20.jar;/Users/mila/.m2/repository/org/ow2/asm/asm/5.0.2/asm-5.0.2.jar;/Users/mila/.m2/repository/org/ow2/asm/asm-commons/5.0.2/asm-commons-5.0.2.jar;/Users/mila/.m2/repository/org/ow2/asm/asm-tree/5.0.2/asm-tree-5.0.2.jar;/Users/mila/.m2/repository/org/freemarker/freemarker/2.3.19/freemarker-2.3.19.jar;/Users/mila/.m2/repository/ognl/ognl/3.0.6/ognl-3.0.6.jar;/Users/mila/.m2/repository/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar;/Users/mila/.m2/repository/commons-fileupload/commons-fileupload/1.3.1/commons-fileupload-1.3.1.jar;/Users/mila/.m2/repository/commons-io/commons-io/2.2/commons-io-2.2.jar;/Users/mila/.m2/repository/org/apache/struts/struts2-spring-plugin/2.3.20/struts2-spring-plugin-2.3.20.jar;/Users/mila/.m2/repository/org/apache/commons/commons-lang3/3.2/commons-lang3-3.2.jar;/Users/mila/.m2/repository/org/zeroturnaround/zt-zip/1.12/zt-zip-1.12.jar;/Users/mila/.m2/repository/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar 42 | [INFO] ------------------------------------------------------------------------ 43 | [INFO] Reactor Summary for Todolist MVC parent module 1.0-SNAPSHOT: 44 | [INFO] 45 | [INFO] Todolist MVC parent module ......................... SUCCESS [ 1.307 s] 46 | [INFO] todolist-core ...................................... SUCCESS [ 0.151 s] 47 | [INFO] todolist-web-common ................................ SUCCESS [ 0.068 s] 48 | [INFO] todolist-web-struts Maven Webapp ................... SUCCESS [ 0.121 s] 49 | [INFO] ------------------------------------------------------------------------ 50 | [INFO] BUILD SUCCESS 51 | [INFO] ------------------------------------------------------------------------ 52 | [INFO] Total time: 2.031 s 53 | [INFO] Finished at: 2020-01-27T17:39:56+01:00 54 | [INFO] ------------------------------------------------------------------------ 55 | -------------------------------------------------------------------------------- /test/fixtures/java-goof-mvn-dependency-plugin-output-line-feed.txt: -------------------------------------------------------------------------------- 1 | [INFO] Scanning for projects... 2 | [INFO] ------------------------------------------------------------------------ 3 | [INFO] Reactor Build Order: 4 | [INFO] 5 | [INFO] Todolist MVC parent module [pom] 6 | [INFO] todolist-core [jar] 7 | [INFO] todolist-web-common [jar] 8 | [INFO] todolist-web-struts Maven Webapp [war] 9 | [INFO] 10 | [INFO] --------------------< io.github.snyk:todolist-mvc >--------------------- 11 | [INFO] Building Todolist MVC parent module 1.0-SNAPSHOT [1/4] 12 | [INFO] --------------------------------[ pom ]--------------------------------- 13 | [INFO] 14 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-mvc --- 15 | [INFO] No dependencies found. 16 | [INFO] Dependencies classpath: 17 | 18 | [INFO] 19 | [INFO] --------------------< io.github.snyk:todolist-core >-------------------- 20 | [INFO] Building todolist-core 1.0-SNAPSHOT [2/4] 21 | [INFO] --------------------------------[ jar ]--------------------------------- 22 | [INFO] 23 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-core --- 24 | [INFO] Dependencies classpath: 25 | /Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/mila/.m2/repository/junit/junit/4.12/junit-4.12.jar:/Users/mila/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/mila/.m2/repository/org/springframework/spring-test/3.2.6.RELEASE/spring-test-3.2.6.RELEASE.jar 26 | [INFO] 27 | [INFO] -----------------< io.github.snyk:todolist-web-common >----------------- 28 | [INFO] Building todolist-web-common 1.0-SNAPSHOT [3/4] 29 | [INFO] --------------------------------[ jar ]--------------------------------- 30 | [INFO] 31 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-web-common --- 32 | [INFO] Dependencies classpath: 33 | /Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar:/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar:/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar 34 | [INFO] 35 | [INFO] -----------------< io.github.snyk:todolist-web-struts >----------------- 36 | [INFO] Building todolist-web-struts Maven Webapp 1.0-SNAPSHOT [4/4] 37 | [INFO] --------------------------------[ war ]--------------------------------- 38 | [INFO] 39 | [INFO] --- maven-dependency-plugin:2.9:build-classpath (default-cli) @ todolist-web-struts --- 40 | [INFO] Dependencies classpath: 41 | /Users/mila/.m2/repository/io/github/snyk/todolist-web-common/1.0-SNAPSHOT/todolist-web-common-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar:/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar:/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar:/Users/mila/.m2/repository/org/springframework/spring-web/3.2.6.RELEASE/spring-web-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/apache/struts/struts2-core/2.3.20/struts2-core-2.3.20.jar:/Users/mila/.m2/repository/org/apache/struts/xwork/xwork-core/2.3.20/xwork-core-2.3.20.jar:/Users/mila/.m2/repository/org/ow2/asm/asm/5.0.2/asm-5.0.2.jar:/Users/mila/.m2/repository/org/ow2/asm/asm-commons/5.0.2/asm-commons-5.0.2.jar:/Users/mila/.m2/repository/org/ow2/asm/asm-tree/5.0.2/asm-tree-5.0.2.jar:/Users/mila/.m2/repository/org/freemarker/freemarker/2.3.19/freemarker-2.3.19.jar:/Users/mila/.m2/repository/ognl/ognl/3.0.6/ognl-3.0.6.jar:/Users/mila/.m2/repository/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar:/Users/mila/.m2/repository/commons-fileupload/commons-fileupload/1.3.1/commons-fileupload-1.3.1.jar:/Users/mila/.m2/repository/commons-io/commons-io/2.2/commons-io-2.2.jar:/Users/mila/.m2/repository/org/apache/struts/struts2-spring-plugin/2.3.20/struts2-spring-plugin-2.3.20.jar:/Users/mila/.m2/repository/org/apache/commons/commons-lang3/3.2/commons-lang3-3.2.jar:/Users/mila/.m2/repository/org/zeroturnaround/zt-zip/1.12/zt-zip-1.12.jar:/Users/mila/.m2/repository/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar 42 | [INFO] ------------------------------------------------------------------------ 43 | [INFO] Reactor Summary for Todolist MVC parent module 1.0-SNAPSHOT: 44 | [INFO] 45 | [INFO] Todolist MVC parent module ......................... SUCCESS [ 1.307 s] 46 | [INFO] todolist-core ...................................... SUCCESS [ 0.151 s] 47 | [INFO] todolist-web-common ................................ SUCCESS [ 0.068 s] 48 | [INFO] todolist-web-struts Maven Webapp ................... SUCCESS [ 0.121 s] 49 | [INFO] ------------------------------------------------------------------------ 50 | [INFO] BUILD SUCCESS 51 | [INFO] ------------------------------------------------------------------------ 52 | [INFO] Total time: 2.031 s 53 | [INFO] Finished at: 2020-01-27T17:39:56+01:00 54 | [INFO] ------------------------------------------------------------------------ 55 | -------------------------------------------------------------------------------- /test/fixtures/java-goof-mvn-exec-output-line-feed-and-carriage-return.txt: -------------------------------------------------------------------------------- 1 | /Users/mila/code/snyk/java-goof/./target/classes 2 | /Users/mila/code/snyk/java-goof/todolist-core/target/classes;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar 3 | /Users/mila/code/snyk/java-goof/todolist-web-common/target/classes;/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar;/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar;/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar;/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar 4 | /Users/mila/code/snyk/java-goof/todolist-web-struts/target/classes;/Users/mila/.m2/repository/io/github/snyk/todolist-web-common/1.0-SNAPSHOT/todolist-web-common-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar;/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar;/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar;/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar;/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar;/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar;/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar;/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar;/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar;/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar;/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar;/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar;/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar;/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar;/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar;/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar;/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar;/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar;/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar;/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar;/Users/mila/.m2/repository/org/springframework/spring-web/3.2.6.RELEASE/spring-web-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar;/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar;/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;/Users/mila/.m2/repository/org/apache/struts/struts2-core/2.3.20/struts2-core-2.3.20.jar;/Users/mila/.m2/repository/org/apache/struts/xwork/xwork-core/2.3.20/xwork-core-2.3.20.jar;/Users/mila/.m2/repository/org/ow2/asm/asm/5.0.2/asm-5.0.2.jar;/Users/mila/.m2/repository/org/ow2/asm/asm-commons/5.0.2/asm-commons-5.0.2.jar;/Users/mila/.m2/repository/org/ow2/asm/asm-tree/5.0.2/asm-tree-5.0.2.jar;/Users/mila/.m2/repository/org/freemarker/freemarker/2.3.19/freemarker-2.3.19.jar;/Users/mila/.m2/repository/ognl/ognl/3.0.6/ognl-3.0.6.jar;/Users/mila/.m2/repository/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar;/Users/mila/.m2/repository/commons-fileupload/commons-fileupload/1.3.1/commons-fileupload-1.3.1.jar;/Users/mila/.m2/repository/commons-io/commons-io/2.2/commons-io-2.2.jar;/Users/mila/.m2/repository/org/apache/struts/struts2-spring-plugin/2.3.20/struts2-spring-plugin-2.3.20.jar;/Users/mila/.m2/repository/org/apache/commons/commons-lang3/3.2/commons-lang3-3.2.jar;/Users/mila/.m2/repository/org/zeroturnaround/zt-zip/1.12/zt-zip-1.12.jar;/Users/mila/.m2/repository/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar 5 | -------------------------------------------------------------------------------- /test/fixtures/java-goof-mvn-exec-output-line-feed.txt: -------------------------------------------------------------------------------- 1 | /Users/mila/code/snyk/java-goof/./target/classes 2 | /Users/mila/code/snyk/java-goof/todolist-core/target/classes:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar 3 | /Users/mila/code/snyk/java-goof/todolist-web-common/target/classes:/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar:/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar:/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar 4 | /Users/mila/code/snyk/java-goof/todolist-web-struts/target/classes:/Users/mila/.m2/repository/io/github/snyk/todolist-web-common/1.0-SNAPSHOT/todolist-web-common-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/io/github/snyk/todolist-core/1.0-SNAPSHOT/todolist-core-1.0-SNAPSHOT.jar:/Users/mila/.m2/repository/org/springframework/spring-orm/3.2.6.RELEASE/spring-orm-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-jdbc/3.2.6.RELEASE/spring-jdbc-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-tx/3.2.6.RELEASE/spring-tx-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-aspects/3.2.6.RELEASE/spring-aspects-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context-support/3.2.6.RELEASE/spring-context-support-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar:/Users/mila/.m2/repository/asm/asm/3.3.1/asm-3.3.1.jar:/Users/mila/.m2/repository/org/aspectj/aspectjweaver/1.8.2/aspectjweaver-1.8.2.jar:/Users/mila/.m2/repository/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar:/Users/mila/.m2/repository/org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-core/4.3.7.Final/hibernate-core-4.3.7.Final.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging-annotations/1.2.0.Beta1/jboss-logging-annotations-1.2.0.Beta1.jar:/Users/mila/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar:/Users/mila/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/Users/mila/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/Users/mila/.m2/repository/org/hibernate/common/hibernate-commons-annotations/4.0.5.Final/hibernate-commons-annotations-4.0.5.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/Users/mila/.m2/repository/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar:/Users/mila/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/mila/.m2/repository/org/jboss/jandex/1.1.0.Final/jandex-1.1.0.Final.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-entitymanager/4.3.7.Final/hibernate-entitymanager-4.3.7.Final.jar:/Users/mila/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar:/Users/mila/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/mila/.m2/repository/javax/servlet/jstl/1.2/jstl-1.2.jar:/Users/mila/.m2/repository/org/hibernate/hibernate-validator/4.3.1.Final/hibernate-validator-4.3.1.Final.jar:/Users/mila/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/Users/mila/.m2/repository/org/jboss/logging/jboss-logging/3.1.0.CR2/jboss-logging-3.1.0.CR2.jar:/Users/mila/.m2/repository/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar:/Users/mila/.m2/repository/org/springframework/spring-web/3.2.6.RELEASE/spring-web-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/mila/.m2/repository/org/springframework/spring-aop/3.2.6.RELEASE/spring-aop-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-beans/3.2.6.RELEASE/spring-beans-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-context/3.2.6.RELEASE/spring-context-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-expression/3.2.6.RELEASE/spring-expression-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/org/springframework/spring-core/3.2.6.RELEASE/spring-core-3.2.6.RELEASE.jar:/Users/mila/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/Users/mila/.m2/repository/org/apache/struts/struts2-core/2.3.20/struts2-core-2.3.20.jar:/Users/mila/.m2/repository/org/apache/struts/xwork/xwork-core/2.3.20/xwork-core-2.3.20.jar:/Users/mila/.m2/repository/org/ow2/asm/asm/5.0.2/asm-5.0.2.jar:/Users/mila/.m2/repository/org/ow2/asm/asm-commons/5.0.2/asm-commons-5.0.2.jar:/Users/mila/.m2/repository/org/ow2/asm/asm-tree/5.0.2/asm-tree-5.0.2.jar:/Users/mila/.m2/repository/org/freemarker/freemarker/2.3.19/freemarker-2.3.19.jar:/Users/mila/.m2/repository/ognl/ognl/3.0.6/ognl-3.0.6.jar:/Users/mila/.m2/repository/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar:/Users/mila/.m2/repository/commons-fileupload/commons-fileupload/1.3.1/commons-fileupload-1.3.1.jar:/Users/mila/.m2/repository/commons-io/commons-io/2.2/commons-io-2.2.jar:/Users/mila/.m2/repository/org/apache/struts/struts2-spring-plugin/2.3.20/struts2-spring-plugin-2.3.20.jar:/Users/mila/.m2/repository/org/apache/commons/commons-lang3/3.2/commons-lang3-3.2.jar:/Users/mila/.m2/repository/org/zeroturnaround/zt-zip/1.12/zt-zip-1.12.jar:/Users/mila/.m2/repository/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar 5 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | */ 4 | 5 | plugins { 6 | id 'java' 7 | id 'maven-publish' 8 | id 'application' 9 | } 10 | 11 | apply plugin : "java" 12 | ext { 13 | javaMainClass = "Unzipper" 14 | } 15 | 16 | application { 17 | mainClassName = javaMainClass 18 | } 19 | 20 | repositories { 21 | mavenLocal() 22 | maven { 23 | url = uri('https://repo.maven.apache.org/maven2') 24 | } 25 | } 26 | 27 | dependencies { 28 | implementation 'commons-collections:commons-collections:3.2.1' 29 | implementation 'org.nd4j:nd4j-common:1.0.0-beta2' 30 | } 31 | 32 | group = 'org.example' 33 | version = '1.0-SNAPSHOT' 34 | sourceCompatibility = '1.8' 35 | 36 | publishing { 37 | publications { 38 | maven(MavenPublication) { 39 | from(components.java) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/classes/java/main/Butler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/build/classes/java/main/Butler.class -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/classes/java/main/Unzipper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/build/classes/java/main/Unzipper.class -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/distributions/java-reachable-goof-1.0-SNAPSHOT.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/build/distributions/java-reachable-goof-1.0-SNAPSHOT.tar -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/distributions/java-reachable-goof-1.0-SNAPSHOT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/build/distributions/java-reachable-goof-1.0-SNAPSHOT.zip -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/libs/java-reachable-goof-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/build/libs/java-reachable-goof-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/scripts/java-reachable-goof: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## java-reachable-goof start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/.." >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="java-reachable-goof" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and JAVA_REACHABLE_GOOF_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS="" 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/lib/java-reachable-goof-1.0-SNAPSHOT.jar:$APP_HOME/lib/commons-collections-3.2.1.jar:$APP_HOME/lib/nd4j-common-1.0.0-beta2.jar:$APP_HOME/lib/jackson-1.0.0-beta2.jar:$APP_HOME/lib/slf4j-api-1.7.21.jar:$APP_HOME/lib/commons-io-2.5.jar:$APP_HOME/lib/commons-math3-3.5.jar:$APP_HOME/lib/commons-lang3-3.6.jar:$APP_HOME/lib/commons-compress-1.16.1.jar:$APP_HOME/lib/guava-20.0.jar:$APP_HOME/lib/commons-codec-1.10.jar:$APP_HOME/lib/snakeyaml-1.12.jar:$APP_HOME/lib/stax2-api-3.1.4.jar:$APP_HOME/lib/joda-time-2.2.jar:$APP_HOME/lib/objenesis-2.6.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $JAVA_REACHABLE_GOOF_OPTS -classpath "\"$CLASSPATH\"" Unzipper "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/scripts/java-reachable-goof.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem java-reachable-goof startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME%.. 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and JAVA_REACHABLE_GOOF_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS= 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\lib\java-reachable-goof-1.0-SNAPSHOT.jar;%APP_HOME%\lib\commons-collections-3.2.1.jar;%APP_HOME%\lib\nd4j-common-1.0.0-beta2.jar;%APP_HOME%\lib\jackson-1.0.0-beta2.jar;%APP_HOME%\lib\slf4j-api-1.7.21.jar;%APP_HOME%\lib\commons-io-2.5.jar;%APP_HOME%\lib\commons-math3-3.5.jar;%APP_HOME%\lib\commons-lang3-3.6.jar;%APP_HOME%\lib\commons-compress-1.16.1.jar;%APP_HOME%\lib\guava-20.0.jar;%APP_HOME%\lib\commons-codec-1.10.jar;%APP_HOME%\lib\snakeyaml-1.12.jar;%APP_HOME%\lib\stax2-api-3.1.4.jar;%APP_HOME%\lib\joda-time-2.2.jar;%APP_HOME%\lib\objenesis-2.6.jar 71 | 72 | 73 | @rem Execute java-reachable-goof 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %JAVA_REACHABLE_GOOF_OPTS% -classpath "%CLASSPATH%" Unzipper %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable JAVA_REACHABLE_GOOF_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%JAVA_REACHABLE_GOOF_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/tmp/compileJava/source-classes-mapping.txt: -------------------------------------------------------------------------------- 1 | Unzipper.java 2 | Unzipper 3 | Butler.java 4 | Butler 5 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/build/tmp/jar/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/init.gradle: -------------------------------------------------------------------------------- 1 | println "Hi" 2 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | java-reachable-goof 9 | 1.0-SNAPSHOT 10 | 11 | 1.8 12 | 1.8 13 | 14 | 15 | 16 | commons-collections 17 | commons-collections 18 | 3.2.1 19 | 20 | 21 | org.nd4j 22 | nd4j-common 23 | 1.0.0-beta2 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/settings.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/target/classes/Butler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/target/classes/Butler.class -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/target/classes/Unzipper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/target/classes/Unzipper.class -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/java-reachability-playground/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst -------------------------------------------------------------------------------- /test/fixtures/java-reachability-playground/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /Users/mila/code/snyk/java-reachable-goof/src/main/java/Unzipper.java 2 | -------------------------------------------------------------------------------- /test/fixtures/snyk-call-graph-generator.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 2 | -------------------------------------------------------------------------------- /test/fixtures/snyk-call-graph-generator_old.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snyk/java-call-graph-builder/a135b36c5e52f17d5d1fcf4209d47d32b1131199/test/fixtures/snyk-call-graph-generator_old.txt -------------------------------------------------------------------------------- /test/integration/e2e-run_gradle.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from '../../lib/promisified-fs-glob'; 3 | import { getCallGraphGradle } from '../../lib'; 4 | 5 | jest.setTimeout(60000); 6 | 7 | let tmpFilePath; 8 | test('callgraph for gradle is created without an init script', async () => { 9 | const mkdtempSpy = jest.spyOn(fs, 'mkdtemp'); 10 | const writeFileSpy = jest.spyOn(fs, 'writeFile'); 11 | await getCallGraphGradle( 12 | path.join( 13 | __dirname, 14 | ...'../fixtures/java-reachability-playground'.split('/'), 15 | ), 16 | ); 17 | 18 | // verify tempdir was created and file written 19 | expect(mkdtempSpy.mock.calls.length).toEqual(1); 20 | expect(writeFileSpy.mock.calls.length).toEqual(1); 21 | tmpFilePath = writeFileSpy.mock.calls[0][0]; 22 | }); 23 | 24 | test('callgraph for gradle is created with an init script', async () => { 25 | const mkdtempSpy = jest.spyOn(fs, 'mkdtemp'); 26 | const writeFileSpy = jest.spyOn(fs, 'writeFile'); 27 | mkdtempSpy.mockClear(); // removes preserved state given by previous test 28 | writeFileSpy.mockClear(); 29 | await getCallGraphGradle( 30 | path.join( 31 | __dirname, 32 | ...'../fixtures/java-reachability-playground'.split('/'), 33 | ), 34 | 'gradle', 35 | 'init.gradle', 36 | ); 37 | 38 | // verify tempdir was created and file written 39 | expect(mkdtempSpy.mock.calls.length).toEqual(1); 40 | expect(writeFileSpy.mock.calls.length).toEqual(1); 41 | tmpFilePath = writeFileSpy.mock.calls[0][0]; 42 | }); 43 | 44 | afterAll(async () => { 45 | // verify tmp file was written; deletion is not awaited in main function, 46 | // therefore it is verified after it finishes 47 | expect(await fs.exists(tmpFilePath)).toBeFalsy(); 48 | }); 49 | -------------------------------------------------------------------------------- /test/integration/e2e-run_mvn.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from '../../lib/promisified-fs-glob'; 3 | 4 | import { getCallGraphMvn } from '../../lib'; 5 | 6 | jest.setTimeout(60000); 7 | 8 | let tmpFilePath; 9 | 10 | describe('callgraph for maven', () => { 11 | it('callgraph for maven is created', async () => { 12 | const mkdtempSpy = jest.spyOn(fs, 'mkdtemp'); 13 | const writeFileSpy = jest.spyOn(fs, 'writeFile'); 14 | await getCallGraphMvn( 15 | path.join( 16 | __dirname, 17 | ...'../fixtures/java-reachability-playground'.split('/'), 18 | ), 19 | ); 20 | 21 | // verify tempdir was created and file written 22 | expect(mkdtempSpy.mock.calls.length).toEqual(1); 23 | expect(writeFileSpy.mock.calls.length).toEqual(1); 24 | tmpFilePath = writeFileSpy.mock.calls[0][0]; 25 | }); 26 | 27 | it(`callgraph for maven is created when given a file that exists`, async () => { 28 | const mkdtempSpy = jest.spyOn(fs, 'mkdtemp'); 29 | const writeFileSpy = jest.spyOn(fs, 'writeFile'); 30 | await getCallGraphMvn( 31 | path.join( 32 | __dirname, 33 | ...'../fixtures/java-reachability-playground'.split('/'), 34 | ), 35 | undefined, 36 | ['-s=settings.xml'], 37 | ); 38 | 39 | // verify tempdir was not created and file not written 40 | expect(mkdtempSpy.mock.calls.length).toEqual(1); 41 | expect(writeFileSpy.mock.calls.length).toEqual(1); 42 | tmpFilePath = writeFileSpy.mock.calls[0][0]; 43 | }); 44 | 45 | it(`throws an error when given a file that doesn't exist`, async () => { 46 | await expect( 47 | getCallGraphMvn( 48 | path.join( 49 | __dirname, 50 | ...'../fixtures/java-reachability-playground'.split('/'), 51 | ), 52 | undefined, 53 | ['-s=nonexistingfile.xml'], 54 | ), 55 | ).rejects.toThrow(); 56 | }); 57 | 58 | it(`callgraph for maven is created when given an empty arr`, async () => { 59 | const mkdtempSpy = jest.spyOn(fs, 'mkdtemp'); 60 | const writeFileSpy = jest.spyOn(fs, 'writeFile'); 61 | await getCallGraphMvn( 62 | path.join( 63 | __dirname, 64 | ...'../fixtures/java-reachability-playground'.split('/'), 65 | ), 66 | undefined, 67 | [], 68 | ); 69 | 70 | // verify tempdir was created and file written 71 | expect(mkdtempSpy.mock.calls.length).toEqual(1); 72 | expect(writeFileSpy.mock.calls.length).toEqual(1); 73 | tmpFilePath = writeFileSpy.mock.calls[0][0]; 74 | }); 75 | 76 | it(`throws an error when given a wrong argument`, async () => { 77 | await expect( 78 | getCallGraphMvn( 79 | path.join( 80 | __dirname, 81 | ...'../fixtures/java-reachability-playground'.split('/'), 82 | ), 83 | undefined, 84 | ['-something=settings.xml'], 85 | ), 86 | ).rejects.toThrow(); 87 | }); 88 | 89 | afterEach(() => { 90 | jest.clearAllMocks(); 91 | }); 92 | 93 | afterAll(async () => { 94 | // verify tmp file was written; deletion is not awaited in main function, 95 | // therefore it is verified after it finishes 96 | expect(await fs.exists(tmpFilePath)).toBeFalsy(); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /test/integration/fetch-snyk-java-call-graph-generator.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as tempDir from 'temp-dir'; 3 | 4 | import * as config from '../../lib/config'; 5 | import * as fetchSnykJavaCallGraphGenerator from '../../lib/fetch-snyk-java-call-graph-generator'; 6 | 7 | jest.setTimeout(30000); 8 | test('check real java call graph builder checksum', async () => { 9 | const jarPath = path.join( 10 | tempDir, 11 | 'call-graph-generator', 12 | fetchSnykJavaCallGraphGenerator.JAR_NAME, 13 | ); 14 | 15 | expect( 16 | await fetchSnykJavaCallGraphGenerator.fetch( 17 | config.CALL_GRAPH_GENERATOR_URL, 18 | config.CALL_GRAPH_GENERATOR_CHECKSUM, 19 | ), 20 | ).toEqual(jarPath); 21 | }); 22 | -------------------------------------------------------------------------------- /test/lib/call-graph.test.ts: -------------------------------------------------------------------------------- 1 | import { buildCallGraph } from '../../lib/call-graph'; 2 | import { promisify } from 'util'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | import * as graphlib from '@snyk/graphlib'; 6 | 7 | const readFile = promisify(fs.readFile); 8 | 9 | test('parse example call graph', async () => { 10 | const callGraph = await readFile( 11 | path.join(__dirname, '../fixtures/call-graph.txt'), 12 | 'utf-8', 13 | ); 14 | const jarMapping = { 15 | 'io.github.todolist.core.domain.Priority': 'todolist-core-1.0-SNAPSHOT.jar', 16 | 'io.github.todolist.core.domain.Todo': 'todolist-core-1.0-SNAPSHOT.jar', 17 | 'io.github.todolist.core.domain.User': 'todolist-core-1.0-SNAPSHOT.jar', 18 | 'io.github.todolist.core.repository.api.TodoRepository': 19 | 'todolist-core-1.0-SNAPSHOT.jar', 20 | 'io.github.todolist.core.repository.api.UserRepository': 21 | 'todolist-core-1.0-SNAPSHOT.jar', 22 | 'io.github.todolist.core.repository.impl.TodoRepositoryImpl': 23 | 'todolist-core-1.0-SNAPSHOT.jar', 24 | 'io.github.todolist.core.repository.impl.UserRepositoryImpl': 25 | 'todolist-core-1.0-SNAPSHOT.jar', 26 | 'io.github.todolist.core.service.api.TodoService': 27 | 'todolist-core-1.0-SNAPSHOT.jar', 28 | 'io.github.todolist.core.service.api.UserService': 29 | 'todolist-core-1.0-SNAPSHOT.jar', 30 | 'io.github.todolist.core.service.impl.TodoServiceImpl': 31 | 'todolist-core-1.0-SNAPSHOT.jar', 32 | 'io.github.todolist.core.service.impl.UserServiceImpl': 33 | 'todolist-core-1.0-SNAPSHOT.jar', 34 | }; 35 | const expectedCallGraph = JSON.parse( 36 | await readFile( 37 | path.join(__dirname, '../fixtures/expected-call-graph.json'), 38 | 'utf-8', 39 | ), 40 | ); 41 | const res = buildCallGraph(callGraph, jarMapping); 42 | expect(graphlib.json.write(res)).toEqual(expectedCallGraph); 43 | }); 44 | -------------------------------------------------------------------------------- /test/lib/classpath.test.ts: -------------------------------------------------------------------------------- 1 | import { ClassPath } from '../../lib/classpath'; 2 | import * as path from 'path'; 3 | 4 | test('ClassPath', () => { 5 | expect( 6 | new ClassPath(`${path.delimiter}${path.delimiter}`).toString(), 7 | ).toEqual(''); 8 | expect(new ClassPath('').concat(new ClassPath('')).toString()).toEqual(''); 9 | expect( 10 | new ClassPath(`aaa${path.delimiter}bbb`) 11 | .concat(new ClassPath('ccc')) 12 | .toString(), 13 | ).toEqual(`aaa${path.delimiter}bbb${path.delimiter}ccc`); 14 | expect( 15 | new ClassPath(`aaa${path.delimiter}bbb`) 16 | .concat(new ClassPath('')) 17 | .toString(), 18 | ).toEqual(`aaa${path.delimiter}bbb`); 19 | expect( 20 | new ClassPath('') 21 | .concat(new ClassPath(`aaa${path.delimiter}bbb`)) 22 | .toString(), 23 | ).toEqual(`aaa${path.delimiter}bbb`); 24 | expect( 25 | new ClassPath(`aaa${path.delimiter}`) 26 | .concat(new ClassPath('bbb')) 27 | .toString(), 28 | ).toEqual(`aaa${path.delimiter}bbb`); 29 | expect( 30 | new ClassPath(`aaa${path.delimiter}`) 31 | .concat(new ClassPath(`${path.delimiter}bbb`)) 32 | .toString(), 33 | ).toEqual(`aaa${path.delimiter}bbb`); 34 | expect(new ClassPath('').concat(new ClassPath('')).toString()).toEqual(''); 35 | }); 36 | -------------------------------------------------------------------------------- /test/lib/fetch-snyk-java-call-graph-generator.test.ts: -------------------------------------------------------------------------------- 1 | import * as fetchSnykJavaCallGraphGenerator from '../../lib/fetch-snyk-java-call-graph-generator'; 2 | import * as nock from 'nock'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | import * as tempDir from 'temp-dir'; 6 | import * as needle from 'needle'; 7 | 8 | import * as promisifiedFs from '../../lib/promisified-fs-glob'; 9 | 10 | nock.disableNetConnect(); 11 | const tmpPath = path.join( 12 | tempDir, 13 | 'call-graph-generator', 14 | fetchSnykJavaCallGraphGenerator.JAR_NAME, 15 | ); 16 | 17 | beforeEach(async () => { 18 | jest.restoreAllMocks(); 19 | try { 20 | fs.unlinkSync(tmpPath); 21 | } catch (e) { 22 | // ignore 23 | } 24 | }); 25 | 26 | const URL = 'https://snyk.test/resources/testing-address.jar'; 27 | const EXPECTED_CHECKSUM = 28 | '56293a80e0394d252e995f2debccea8223e4b5b2b150bee212729b3b39ac4d46'; 29 | 30 | test('analyzer is fetched when does not exist', async () => { 31 | nock('https://snyk.test') 32 | .get('/resources/testing-address.jar') 33 | .replyWithFile( 34 | 200, 35 | __dirname + '/../fixtures/snyk-call-graph-generator.txt', 36 | { 'Content-Length': '446' }, 37 | ); 38 | 39 | expect( 40 | await fetchSnykJavaCallGraphGenerator.fetch(URL, EXPECTED_CHECKSUM), 41 | ).toEqual(tmpPath); 42 | }); 43 | 44 | test('analyzer is not fetched when actual version is available', async () => { 45 | jest.spyOn(promisifiedFs, 'exists').mockResolvedValue(true); 46 | jest 47 | .spyOn(fs, 'createReadStream') 48 | .mockReturnValue( 49 | fs.createReadStream( 50 | path.join(__dirname, '../fixtures/snyk-call-graph-generator.txt'), 51 | ), 52 | ); 53 | jest.spyOn(needle, 'get'); 54 | expect( 55 | await fetchSnykJavaCallGraphGenerator.fetch(URL, EXPECTED_CHECKSUM), 56 | ).toEqual(tmpPath); 57 | expect(needle.get).not.toHaveBeenCalled(); 58 | }); 59 | 60 | test('analyzer is fetched when older version is available', async () => { 61 | jest.spyOn(promisifiedFs, 'exists').mockResolvedValue(true); 62 | 63 | nock('https://snyk.test') 64 | .get('/resources/testing-address.jar') 65 | .replyWithFile( 66 | 200, 67 | __dirname + '/../fixtures/snyk-call-graph-generator.txt', 68 | { 'Content-Length': '446' }, 69 | ); 70 | 71 | jest.spyOn(fs, 'createReadStream').mockImplementationOnce(() => { 72 | return fs.createReadStream( 73 | path.join(__dirname, '../fixtures/snyk-call-graph-generator_old.txt'), 74 | ); 75 | }); 76 | 77 | const a = await fetchSnykJavaCallGraphGenerator.fetch(URL, EXPECTED_CHECKSUM); 78 | expect(a).toEqual(tmpPath); 79 | }); 80 | 81 | test('analyzer fetch error is caught', async () => { 82 | nock('https://snyk.test') 83 | .get('/resources/testing-address.jar') 84 | .reply(404); 85 | await expect( 86 | fetchSnykJavaCallGraphGenerator.fetch(URL, EXPECTED_CHECKSUM), 87 | ).rejects.toThrowError( 88 | 'Bad HTTP response for snyk-call-graph-generator download', 89 | ); 90 | }); 91 | 92 | test('analyzer wrong checksum after download is caught', async () => { 93 | nock('https://snyk.test') 94 | .get('/resources/testing-address.jar') 95 | .replyWithFile( 96 | 200, 97 | __dirname + '/../fixtures/snyk-call-graph-generator_old.txt', 98 | { 'Content-Length': '446' }, 99 | ); 100 | 101 | await expect( 102 | fetchSnykJavaCallGraphGenerator.fetch(URL, EXPECTED_CHECKSUM), 103 | ).rejects.toThrowError('Wrong checksum of downloaded call-graph-generator.'); 104 | }); 105 | -------------------------------------------------------------------------------- /test/lib/gradle-wrapper.test.ts: -------------------------------------------------------------------------------- 1 | import { getGradleCommandArgs } from '../../lib/gradle-wrapper'; 2 | 3 | import * as path from 'path'; 4 | import { platform } from 'os'; 5 | 6 | test('get right args for gradle command', async () => { 7 | const commandArgs = getGradleCommandArgs( 8 | 'directory_name', 9 | 'some_script.gradle.kts', 10 | ); 11 | const initGradlePath = commandArgs[2]; // Contains a temporary path 12 | expect(commandArgs).toEqual([ 13 | 'printClasspath', 14 | '-I', 15 | initGradlePath, 16 | '-q', 17 | '-p', 18 | 'directory_name', 19 | '--init-script', 20 | 'some_script.gradle.kts', 21 | ]); 22 | }); 23 | 24 | test('get right args for gradle command without init script', async () => { 25 | const commandArgs = getGradleCommandArgs('directory_name'); 26 | const initGradlePath = commandArgs[2]; // Contains a temporary path 27 | expect(commandArgs).toEqual([ 28 | 'printClasspath', 29 | '-I', 30 | initGradlePath, 31 | '-q', 32 | '-p', 33 | 'directory_name', 34 | ]); 35 | }); 36 | 37 | test('get right args for gradle command with configuration attributes', async () => { 38 | const isWin = /^win/.test(platform()); 39 | const quot = isWin ? '"' : "'"; 40 | 41 | const commandArgs = getGradleCommandArgs( 42 | 'directory_name', 43 | undefined, 44 | 'buildtype:release,usage:java-runtime,backend:prod', 45 | ); 46 | const initGradlePath = commandArgs[2]; // Contains a temporary path 47 | 48 | expect(commandArgs).toEqual([ 49 | 'printClasspath', 50 | '-I', 51 | initGradlePath, 52 | '-q', 53 | '-p', 54 | 'directory_name', 55 | `-PconfAttrs=${quot}buildtype:release,usage:java-runtime,backend:prod${quot}`, 56 | ]); 57 | }); 58 | -------------------------------------------------------------------------------- /test/lib/index.test.ts: -------------------------------------------------------------------------------- 1 | import { findBuildDirs } from '../../lib/index'; 2 | import { MissingTargetFolderError } from '../../lib/errors'; 3 | 4 | test('get targets - maven - no target folder throws and error', async () => { 5 | const targetPath = 'some-bogus-folder-that-does-not-exist'; 6 | const expectedError = new MissingTargetFolderError(targetPath, 'mvn'); 7 | expect(findBuildDirs(targetPath, 'mvn')).rejects.toEqual(expectedError); 8 | expect(expectedError.userMessage).toEqual( 9 | "Could not find the project's output directory. Please build your project and try again. The reachable vulnerabilities feature only supports the default Maven project layout, where the output directory is named 'target'.", 10 | ); 11 | }); 12 | 13 | test('get targets - gradle - no target folder throws an error', async () => { 14 | const targetPath = 'some-bogus-folder-that-does-not-exist'; 15 | const expectedError = new MissingTargetFolderError(targetPath, 'gradle'); 16 | 17 | expect(findBuildDirs(targetPath, 'gradle')).rejects.toEqual(expectedError); 18 | expect(expectedError.userMessage).toEqual( 19 | "Could not find the project's target folder. Please compile your code and try again.", 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /test/lib/java-wrapper.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { 3 | getClassPerJarMapping, 4 | getCallGraphGenCommandArgs, 5 | } from '../../lib/java-wrapper'; 6 | 7 | test('classes per jar mapping is created', async () => { 8 | const mapping = await getClassPerJarMapping( 9 | path.join( 10 | __dirname, 11 | ...'../fixtures/example-java-project/target/todolist-core-1.0-SNAPSHOT.jar'.split( 12 | '/', 13 | ), 14 | ), 15 | ); 16 | 17 | for (const item of Object.values(mapping)) { 18 | const root = __dirname.split(path.sep)[0]; 19 | expect(item.startsWith(root)).toBeTruthy(); 20 | expect( 21 | item.endsWith(`${path.sep}todolist-core-1.0-SNAPSHOT.jar`), 22 | ).toBeTruthy(); 23 | } 24 | }); 25 | 26 | test('callgraph arguments contain `--application-path-file`', async () => { 27 | expect( 28 | getCallGraphGenCommandArgs('someFileName', 'someJarPath', []), 29 | ).toContain('--application-classpath-file'); 30 | }); 31 | -------------------------------------------------------------------------------- /test/lib/metrics.test.ts: -------------------------------------------------------------------------------- 1 | import * as metrics from '../../lib/metrics'; 2 | 3 | describe('timing metrics', () => { 4 | test('works if no metrics available', async () => { 5 | expect(metrics.getMetrics()).toBeTruthy(); 6 | }); 7 | 8 | test('should run function being timed', () => { 9 | const result = metrics.timeIt('fetchCallGraphBuilder', () => 10 | Promise.resolve(10), 11 | ); 12 | expect(result).resolves.toBe(10); 13 | }); 14 | 15 | test('should time function correctly', async () => { 16 | const mock = jest.spyOn(process, 'hrtime'); 17 | mock 18 | .mockImplementationOnce(() => [0, 10]) 19 | .mockImplementationOnce(() => [10, 20]); 20 | 21 | await metrics.timeIt('fetchCallGraphBuilder', () => Promise.resolve(10)); 22 | expect(mock).toBeCalledTimes(2); 23 | expect(mock.mock.calls).toEqual([[], [[0, 10]]]); 24 | }); 25 | 26 | test('should return metrics correctly', async () => { 27 | const mock = jest.spyOn(process, 'hrtime'); 28 | mock 29 | .mockImplementationOnce(() => [0, 10]) 30 | .mockImplementationOnce(() => [10, 20]); 31 | 32 | await metrics.timeIt('fetchCallGraphBuilder', () => Promise.resolve(10)); 33 | expect(metrics.getMetrics()).toMatchObject({ 34 | fetchCallGraphBuilder: 10.00000002, 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lib/mvn-wrapper.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MavenModule, 3 | MavenProject, 4 | parseModuleNames, 5 | } from '../../lib/mvn-wrapper'; 6 | import { MalformedModulesSpecError } from '../../lib/errors'; 7 | import { ClassPath } from '../../lib/classpath'; 8 | import * as path from 'path'; 9 | 10 | describe('parseModuleNames', () => { 11 | test('handles empty input', () => { 12 | expect(() => parseModuleNames('')).toThrowError(MalformedModulesSpecError); 13 | }); 14 | 15 | test('throws generic error on junk input', () => { 16 | expect(() => parseModuleNames('junk')).toThrowError(Error); 17 | }); 18 | 19 | test('handles empty module list', () => { 20 | expect(() => parseModuleNames('')).toHaveLength(0); 21 | expect(() => parseModuleNames('')).toHaveLength(0); 22 | }); 23 | 24 | test('throws specific error on malformed input', () => { 25 | expect(() => parseModuleNames(``)).toThrowError( 26 | MalformedModulesSpecError, 27 | ); 28 | }); 29 | 30 | test('handles module list', () => { 31 | expect( 32 | parseModuleNames(` 33 | app 34 | util 35 | `), 36 | ).toEqual(['app', 'util']); 37 | }); 38 | }); 39 | 40 | describe('MavenModule', () => { 41 | test('throws on missing build directory', () => { 42 | expect( 43 | () => new MavenModule('base', '', 'out', new ClassPath('dep')), 44 | ).toThrowError(); 45 | }); 46 | 47 | test('throws on missing output directory', () => { 48 | expect( 49 | () => new MavenModule('base', 'build', '', new ClassPath('dep')), 50 | ).toThrowError(); 51 | }); 52 | 53 | test('throws on missing dependencies classpath', () => { 54 | expect( 55 | () => new MavenModule('base', 'build', 'out', new ClassPath('')), 56 | ).toThrowError(); 57 | }); 58 | 59 | test('builds correct classpath', () => { 60 | const module = new MavenModule( 61 | 'base', 62 | 'build', 63 | 'out', 64 | new ClassPath('dep'), 65 | ); 66 | expect(module.getClassPath().toString()).toEqual(`dep${path.delimiter}out`); 67 | }); 68 | }); 69 | 70 | describe('MavenProject', () => { 71 | test('throws on empty module list', () => { 72 | expect(() => new MavenProject('base', [])).toThrowError(); 73 | }); 74 | 75 | test('builds correct classpath', () => { 76 | const module1 = new MavenModule( 77 | 'base1', 78 | 'build1', 79 | 'out1', 80 | new ClassPath('dep1'), 81 | ); 82 | const module2 = new MavenModule( 83 | 'base2', 84 | 'build2', 85 | 'out2', 86 | new ClassPath('dep2'), 87 | ); 88 | const module3 = new MavenModule( 89 | 'base3', 90 | 'build3', 91 | 'out3', 92 | new ClassPath('dep3'), 93 | ); 94 | const project = new MavenProject('base', [module1, module2, module3]); 95 | expect(project.getClassPath().toString()).toEqual( 96 | `dep1${path.delimiter}out1${path.delimiter}dep2${path.delimiter}out2${path.delimiter}dep3${path.delimiter}out3`, 97 | ); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "pretty": true, 5 | "target": "es2015", 6 | "module": "commonjs", 7 | "sourceMap": true, 8 | "declaration": true, 9 | "importHelpers": true, 10 | "strict": true, 11 | "noImplicitAny": false, 12 | }, 13 | "include": ["./lib/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"], 3 | "rules": { 4 | "triple-equals": true, 5 | "curly": true, 6 | "interface-name": false, 7 | "ordered-imports": false, 8 | "object-literal-sort-keys": false 9 | } 10 | } 11 | --------------------------------------------------------------------------------