├── .editorconfig ├── .github ├── maven-cd-settings.xml ├── maven-ci-settings.xml └── workflows │ ├── ci-4.x.yml │ ├── ci-5.x-stable.yml │ ├── ci-5.x.yml │ ├── ci-matrix-5.x.yml │ ├── ci.yml │ └── deploy.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── pom.xml ├── stack-depchain └── pom.xml ├── stack-docs ├── docs.xml ├── html.xml ├── kotlin.md ├── pom.xml └── src │ └── main │ └── asciidoc │ └── index.adoc └── stack-manager ├── pom.xml └── src ├── main ├── descriptor │ └── vertx-stack-full.json ├── java │ └── io │ │ └── vertx │ │ └── stack │ │ ├── command │ │ ├── ResolveCommand.java │ │ ├── ResolveCommandFactory.java │ │ └── package-info.java │ │ ├── model │ │ ├── Artifact.java │ │ ├── Dependency.java │ │ ├── DependencyConflictException.java │ │ ├── Stack.java │ │ ├── StackResolution.java │ │ └── StackResolutionOptions.java │ │ ├── resolver │ │ ├── ResolutionOptions.java │ │ ├── Resolver.java │ │ ├── ResolverImpl.java │ │ └── ResolverOptions.java │ │ └── utils │ │ ├── Actions.java │ │ ├── Cache.java │ │ ├── Filtering.java │ │ └── Home.java └── resources │ └── META-INF │ └── services │ └── io.vertx.core.spi.launcher.CommandFactory └── test ├── java └── io │ └── vertx │ └── stack │ ├── DescriptorTest.java │ ├── StackResolutionTest.java │ ├── VertxStacksTest.java │ ├── resolver │ └── ResolverTest.java │ └── utils │ ├── CacheTest.java │ ├── FileUtils.java │ ├── FilteringTest.java │ ├── FluentMap.java │ ├── LocalArtifact.java │ ├── LocalDependency.java │ ├── LocalRepoBuilder.java │ └── PomUtils.java └── resources └── stacks ├── core-with-system-variable.json ├── core-with-variable.json ├── core.json ├── vertx-core-only.json └── vertx-web-stack.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.github/maven-cd-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | vertx-snapshots-repository 24 | ${env.VERTX_NEXUS_USERNAME} 25 | ${env.VERTX_NEXUS_PASSWORD} 26 | 27 | 28 | 29 | 30 | 31 | google-mirror 32 | 33 | true 34 | 35 | 36 | 37 | google-maven-central 38 | GCS Maven Central mirror EU 39 | https://maven-central.storage-download.googleapis.com/maven2/ 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | google-maven-central 51 | GCS Maven Central mirror 52 | https://maven-central.storage-download.googleapis.com/maven2/ 53 | 54 | true 55 | 56 | 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /.github/maven-ci-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | google-mirror 24 | 25 | true 26 | 27 | 28 | 29 | google-maven-central 30 | GCS Maven Central mirror EU 31 | https://maven-central.storage-download.googleapis.com/maven2/ 32 | 33 | true 34 | 35 | 36 | false 37 | 38 | 39 | 40 | 41 | 42 | google-maven-central 43 | GCS Maven Central mirror 44 | https://maven-central.storage-download.googleapis.com/maven2/ 45 | 46 | true 47 | 48 | 49 | false 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/ci-4.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-stack (4.x) 2 | on: 3 | schedule: 4 | - cron: '0 4 * * *' 5 | jobs: 6 | CI: 7 | strategy: 8 | matrix: 9 | include: 10 | - os: ubuntu-latest 11 | jdk: 8 12 | uses: ./.github/workflows/ci.yml 13 | with: 14 | branch: 4.x 15 | jdk: ${{ matrix.jdk }} 16 | os: ${{ matrix.os }} 17 | secrets: inherit 18 | Deploy: 19 | if: ${{ github.repository_owner == 'vert-x3' && (github.event_name == 'push' || github.event_name == 'schedule') }} 20 | needs: CI 21 | uses: ./.github/workflows/deploy.yml 22 | with: 23 | branch: 4.x 24 | jdk: 8 25 | secrets: inherit 26 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x-stable.yml: -------------------------------------------------------------------------------- 1 | name: vertx-stack (5.x-stable) 2 | on: 3 | push: 4 | branches: 5 | - '5.[0-9]+' 6 | pull_request: 7 | branches: 8 | - '5.[0-9]+' 9 | schedule: 10 | - cron: '0 6 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event_name == 'schedule' && vars.VERTX_5_STABLE_BRANCH || github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-stack (5.x) 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | schedule: 10 | - cron: '0 5 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-matrix-5.x.yml: -------------------------------------------------------------------------------- 1 | name: CI matrix (5.x) 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jobs: 9 | CI: 10 | strategy: 11 | matrix: 12 | include: 13 | - os: ubuntu-latest 14 | jdk: 11 15 | uses: ./.github/workflows/ci.yml 16 | with: 17 | branch: ${{ inputs.branch }} 18 | jdk: ${{ matrix.jdk }} 19 | os: ${{ matrix.os }} 20 | secrets: inherit 21 | Deploy: 22 | if: ${{ github.repository_owner == 'vert-x3' && (github.event_name == 'push' || github.event_name == 'schedule') }} 23 | needs: CI 24 | uses: ./.github/workflows/deploy.yml 25 | with: 26 | branch: ${{ inputs.branch }} 27 | jdk: 11 28 | secrets: inherit 29 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | os: 12 | default: ubuntu-latest 13 | type: string 14 | jobs: 15 | Test: 16 | name: Run tests 17 | runs-on: ${{ inputs.os }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: joschi/setup-jdk@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | - name: Run tests 28 | run: mvn -q clean verify -B 29 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | jobs: 12 | Deploy: 13 | name: Deploy to OSSRH 14 | runs-on: ubuntu-latest 15 | env: 16 | VERTX_NEXUS_USERNAME: ${{ secrets.VERTX_NEXUS_USERNAME }} 17 | VERTX_NEXUS_PASSWORD: ${{ secrets.VERTX_NEXUS_PASSWORD }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | distribution: temurin 28 | - name: Get project version 29 | run: echo "PROJECT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout | grep -v '\[')" >> $GITHUB_ENV 30 | - name: Maven deploy 31 | if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} 32 | run: mvn deploy -s .github/maven-cd-settings.xml -DskipTests -B 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gradle 3 | .vscode 4 | .idea 5 | .classpath 6 | .project 7 | .settings 8 | .yardoc 9 | .yardopts 10 | build 11 | target 12 | out 13 | *.iml 14 | *.ipr 15 | *.iws 16 | test-output 17 | Scratch.java 18 | ScratchTest.java 19 | test-results 20 | test-tmp 21 | *.class 22 | src/gen 23 | src/main/groovy/io/vertx/groovy/core/**/*.groovy 24 | src/test/groovy/io/vertx/groovy/codegen/**/*.groovy 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vertx-stack 2 | ======== 3 | 4 | [![Build Status (5.x)](https://github.com/vert-x3/vertx-stack/actions/workflows/ci-5.x.yml/badge.svg)](https://github.com/vert-x3/vertx-stack/actions/workflows/ci-5.x.yml) 5 | [![Build Status (4.x)](https://github.com/vert-x3/vertx-stack/actions/workflows/ci-4.x.yml/badge.svg)](https://github.com/vert-x3/vertx-stack/actions/workflows/ci-4.x.yml) 6 | 7 | The Vert.x stack : Vert.x + the endorsed modules 8 | 9 | ### Maven 10 | 11 | This project provides pre-configured Maven poms for using in your projects, allowing you to consume the Vert.x stack 12 | easily. 13 | 14 | #### Dependency chain (_Maven depchain_) 15 | 16 | This artifact `io.vertx:stack-depchain` is a POM projects can import to get the dependencies it needs for running 17 | the base stack: 18 | 19 | ~~~~ 20 | 21 | io.vertx 22 | vertx-stack-depchain 23 | 3.5.1 24 | pom 25 | 26 | ~~~~ 27 | 28 | #### Bills of Materials (Maven _BOM_) 29 | 30 | A [_BOM_](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html) is a also a POM you 31 | can import in your project. It will not add dependencies to your POM, instead it will set the correct versions to use. 32 | Therefore it should be used with explicit dependencies: 33 | 34 | ~~~~ 35 | 36 | 37 | 38 | io.vertx 39 | vertx-stack-depchain 40 | 3.5.1 41 | pom 42 | import 43 | 44 | 45 | 46 | 47 | 48 | 49 | io.vertx 50 | vertx-core 51 | 52 | ... 53 | 54 | ~~~~ 55 | 56 | ### Adding a new module to the stack 57 | 58 | 1. Add it to [`vertx-dependencies`](https://github.com/vert-x3/vertx-dependencies) (open the project, add it to the `pom.xml`, install, commit and push) 59 | 2. Add it to `stack-depchain/pom.xml` (open the project, add the dependency, without the version (inherited from 60 | vertx-dependencies)) 61 | 3. Add it in the stack manager: 62 | * Open `./stack-manager/src/main/descriptor/vertx-stack-full.json` 63 | * Add the dependency. If the dependency must be embedded in the _full_ distribution, set `included` to `true`. Don't forget to use the `\${version}`. 64 | 4. Add it to the doc distribution: 65 | * Open `./stack-docs/pom.xml` 66 | * Add the `docs` dependency (the using `docs` and `zip`) 67 | * Add the `source` dependency (the `sources`) 68 | * Add the _copy_ instruction for the ant execution: 69 | ``` 70 | 71 | 72 | 73 | ``` 74 | * Save the `pom.xml` file 75 | * Build (`mvn clean install` from the root). 76 | 5. Make it polyglot (unless the module is not polyglot, e.g. a cluster manager) 77 | * Kotlin: in [`vertx-lang-kotlin`](https://github.com/vert-x3/vertx-lang-kotlin), edit `vertx-lang-kotlin/pom.xml` 78 | * Add an `optional` dependency to the POM 79 | * Update the list in the `maven-dependency-plugin` config 80 | * RxJava3: in [`vertx-rx`](https://github.com/vert-x3/vertx-rx), edit `rx-java3/pom.xml` 81 | * Add an `optional` dependency to the POM 82 | * Update the list in the `maven-dependency-plugin` config 83 | * RxJava2: in [`vertx-rx`](https://github.com/vert-x3/vertx-rx), edit `rx-java2/pom.xml` 84 | * Add an `optional` dependency to the POM 85 | * Update the list in the `maven-dependency-plugin` config 86 | 6. Add it to the website in [`vertx-web-site`](https://github.com/vertx-web-site/vertx-web-site.github.io): 87 | * Edit the docs summary page `docs/metadata/.jsx`, use `Tech Preview` label 88 | 7. Add it to the starter website in [`vertx-starter`](https://github.com/vert-x3/vertx-starter/): 89 | * Edit the stack definition file `src/main/resources/starter.json` 90 | * Add the module details in one of the categories (web, data, ...etc) 91 | * Exclude the module from versions that did not have it (`exclusions`) 92 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | io.vertx 9 | vertx5-parent 10 | 12 11 | 12 | 13 | vertx-stack 14 | 5.1.0-SNAPSHOT 15 | 16 | Vert.x Stack - Project 17 | pom 18 | 19 | 20 | 21 | The Apache Software License, Version 2.0 22 | http://www.apache.org/licenses/LICENSE-2.0.txt 23 | repo 24 | 25 | 26 | Eclipse Public License - v 1.0 27 | http://www.eclipse.org/legal/epl-v10.html 28 | repo 29 | 30 | 31 | 32 | 33 | 34 | 35 | io.vertx 36 | vertx-dependencies 37 | ${project.version} 38 | pom 39 | import 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | maven-assembly-plugin 49 | 2.4.1 50 | 51 | 52 | 53 | 54 | 55 | 56 | stack-depchain 57 | stack-manager 58 | stack-docs 59 | 60 | 61 | 62 | 63 | 64 | sonatype-oss-release 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-enforcer-plugin 70 | 71 | 72 | enforce-no-snapshots 73 | 74 | enforce 75 | 76 | 77 | 78 | 79 | No Snapshots Allowed during a release! 80 | 81 | io.vertx:* 82 | 83 | 84 | 85 | true 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /stack-depchain/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | io.vertx 9 | vertx-stack 10 | 5.1.0-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | vertx-stack-depchain 15 | 5.1.0-SNAPSHOT 16 | 17 | Vert.x Stack - Dependency Chain 18 | pom 19 | 20 | 21 | 22 | io.vertx 23 | vertx-core 24 | 25 | 26 | io.vertx 27 | vertx-launcher-legacy-cli 28 | 29 | 30 | io.vertx 31 | vertx-launcher-application 32 | 33 | 34 | io.vertx 35 | vertx-lang-groovy 36 | 37 | 38 | io.vertx 39 | vertx-service-proxy 40 | 41 | 42 | io.vertx 43 | vertx-hazelcast 44 | 45 | 46 | io.vertx 47 | vertx-zookeeper 48 | 49 | 50 | io.vertx 51 | vertx-dropwizard-metrics 52 | 53 | 54 | io.vertx 55 | vertx-micrometer-metrics 56 | 57 | 58 | io.vertx 59 | vertx-zipkin 60 | 61 | 62 | io.vertx 63 | vertx-opentracing 64 | 65 | 66 | io.vertx 67 | vertx-opentelemetry 68 | 69 | 70 | io.vertx 71 | vertx-openapi 72 | 73 | 74 | io.vertx 75 | vertx-reactive-streams 76 | 77 | 78 | io.vertx 79 | vertx-rx-java2 80 | 81 | 82 | io.vertx 83 | vertx-rx-java3 84 | 85 | 86 | io.vertx 87 | vertx-consul-client 88 | 89 | 90 | io.vertx 91 | vertx-cassandra-client 92 | 93 | 94 | io.vertx 95 | vertx-mongo-client 96 | 97 | 98 | io.vertx 99 | vertx-jdbc-client 100 | 101 | 102 | io.vertx 103 | vertx-auth-common 104 | 105 | 106 | io.vertx 107 | vertx-auth-htdigest 108 | 109 | 110 | io.vertx 111 | vertx-auth-htpasswd 112 | 113 | 114 | io.vertx 115 | vertx-auth-jwt 116 | 117 | 118 | io.vertx 119 | vertx-auth-oauth2 120 | 121 | 122 | io.vertx 123 | vertx-auth-mongo 124 | 125 | 126 | io.vertx 127 | vertx-auth-properties 128 | 129 | 130 | io.vertx 131 | vertx-auth-ldap 132 | 133 | 134 | io.vertx 135 | vertx-auth-webauthn4j 136 | 137 | 138 | io.vertx 139 | vertx-auth-sql-client 140 | 141 | 142 | io.vertx 143 | vertx-auth-otp 144 | 145 | 146 | io.vertx 147 | vertx-auth-abac 148 | 149 | 150 | io.vertx 151 | vertx-web 152 | 153 | 154 | io.vertx 155 | vertx-web-common 156 | 157 | 158 | io.vertx 159 | vertx-web-client 160 | 161 | 162 | io.vertx 163 | vertx-web-api-service 164 | 165 | 166 | io.vertx 167 | vertx-web-openapi-router 168 | 169 | 170 | io.vertx 171 | vertx-web-sstore-cookie 172 | 173 | 174 | io.vertx 175 | vertx-web-sstore-redis 176 | 177 | 178 | io.vertx 179 | vertx-web-sstore-infinispan 180 | 181 | 182 | io.vertx 183 | vertx-web-templ-thymeleaf 184 | shaded 185 | 186 | 187 | io.vertx 188 | vertx-web-templ-handlebars 189 | shaded 190 | 191 | 192 | io.vertx 193 | vertx-web-templ-pug 194 | shaded 195 | 196 | 197 | io.vertx 198 | vertx-web-templ-mvel 199 | shaded 200 | 201 | 202 | io.vertx 203 | vertx-web-templ-pebble 204 | shaded 205 | 206 | 207 | io.vertx 208 | vertx-web-templ-freemarker 209 | shaded 210 | 211 | 212 | io.vertx 213 | vertx-web-templ-rocker 214 | shaded 215 | 216 | 217 | io.vertx 218 | vertx-web-templ-httl 219 | shaded 220 | 221 | 222 | io.vertx 223 | vertx-web-graphql 224 | 225 | 226 | io.vertx 227 | vertx-web-proxy 228 | 229 | 230 | io.vertx 231 | vertx-web-validation 232 | 233 | 234 | io.vertx 235 | vertx-sockjs-service-proxy 236 | 237 | 238 | io.vertx 239 | vertx-unit 240 | test 241 | 242 | 243 | io.vertx 244 | vertx-junit5 245 | test 246 | 247 | 248 | io.vertx 249 | vertx-junit5-rx-java2 250 | test 251 | 252 | 253 | io.vertx 254 | vertx-junit5-rx-java3 255 | test 256 | 257 | 258 | io.vertx 259 | vertx-mail-client 260 | 261 | 262 | io.vertx 263 | vertx-redis-client 264 | 265 | 266 | io.vertx 267 | vertx-shell 268 | 269 | 270 | io.vertx 271 | vertx-stomp 272 | 273 | 274 | io.vertx 275 | vertx-infinispan 276 | 277 | 278 | io.vertx 279 | vertx-bridge-common 280 | 281 | 282 | io.vertx 283 | vertx-tcp-eventbus-bridge 284 | 285 | 286 | io.vertx 287 | vertx-sql-client 288 | 289 | 290 | io.vertx 291 | vertx-pg-client 292 | 293 | 294 | io.vertx 295 | vertx-mysql-client 296 | 297 | 298 | io.vertx 299 | vertx-db2-client 300 | 301 | 302 | io.vertx 303 | vertx-mssql-client 304 | 305 | 306 | io.vertx 307 | vertx-oracle-client 308 | 309 | 310 | io.vertx 311 | vertx-sql-client-templates 312 | 313 | 314 | io.vertx 315 | vertx-camel-bridge 316 | 317 | 318 | io.vertx 319 | vertx-ignite 320 | 321 | 322 | io.vertx 323 | vertx-rabbitmq-client 324 | 325 | 326 | io.vertx 327 | vertx-service-discovery 328 | 329 | 330 | io.vertx 331 | vertx-circuit-breaker 332 | 333 | 334 | io.vertx 335 | vertx-service-discovery-bridge-kubernetes 336 | 337 | 338 | io.vertx 339 | vertx-service-discovery-bridge-docker-links 340 | 341 | 342 | io.vertx 343 | vertx-service-discovery-bridge-docker 344 | 345 | 346 | io.vertx 347 | vertx-service-discovery-backend-redis 348 | 349 | 350 | io.vertx 351 | vertx-service-discovery-bridge-consul 352 | 353 | 354 | io.vertx 355 | vertx-service-discovery-bridge-zookeeper 356 | 357 | 358 | io.vertx 359 | vertx-config 360 | 361 | 362 | io.vertx 363 | vertx-config-git 364 | 365 | 366 | io.vertx 367 | vertx-config-hocon 368 | 369 | 370 | io.vertx 371 | vertx-config-kubernetes-configmap 372 | 373 | 374 | io.vertx 375 | vertx-config-redis 376 | 377 | 378 | io.vertx 379 | vertx-config-spring-config-server 380 | 381 | 382 | io.vertx 383 | vertx-config-yaml 384 | 385 | 386 | io.vertx 387 | vertx-config-zookeeper 388 | 389 | 390 | io.vertx 391 | vertx-grpc 392 | 393 | 394 | 395 | io.vertx 396 | vertx-proton 397 | 398 | 399 | io.vertx 400 | vertx-amqp-client 401 | 402 | 403 | io.vertx 404 | vertx-kafka-client 405 | 406 | 407 | io.vertx 408 | vertx-json-schema 409 | 410 | 411 | io.vertx 412 | vertx-health-check 413 | 414 | 415 | io.vertx 416 | vertx-mqtt 417 | 418 | 419 | io.vertx 420 | vertx-http-proxy 421 | 422 | 423 | io.vertx 424 | vertx-uri-template 425 | 426 | 427 | io.vertx 428 | vertx-grpc-common 429 | 430 | 431 | io.vertx 432 | vertx-grpc-client 433 | 434 | 435 | io.vertx 436 | vertx-grpc-server 437 | 438 | 439 | io.vertx 440 | vertx-grpcio-common 441 | 442 | 443 | io.vertx 444 | vertx-grpcio-client 445 | 446 | 447 | io.vertx 448 | vertx-grpcio-server 449 | 450 | 451 | io.vertx 452 | vertx-grpc-reflection 453 | 454 | 455 | io.vertx 456 | vertx-grpc-health 457 | 458 | 459 | io.vertx 460 | vertx-grpc-transcoding 461 | 462 | 463 | io.vertx 464 | vertx-service-resolver 465 | 466 | 467 | 468 | 469 | -------------------------------------------------------------------------------- /stack-docs/docs.xml: -------------------------------------------------------------------------------- 1 | 4 | docs 5 | 6 | zip 7 | 8 | false 9 | 10 | 11 | ${project.build.directory}/docs 12 | / 13 | 14 | 15 | -------------------------------------------------------------------------------- /stack-docs/html.xml: -------------------------------------------------------------------------------- 1 | 4 | html 5 | 6 | zip 7 | 8 | false 9 | 10 | 11 | ${project.build.directory}/html 12 | / 13 | 14 | 15 | -------------------------------------------------------------------------------- /stack-docs/kotlin.md: -------------------------------------------------------------------------------- 1 | # Module vertx 2 | 3 | Vert.x for Kotlin API documentation. 4 | -------------------------------------------------------------------------------- /stack-docs/src/main/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | == Documentation 4 | 5 | === Java 6 | 7 | - link:vertx-core/java/index.html[Core] 8 | - link:vertx-launcher-application/java/index.html[Application Launcher] 9 | - link:vertx-web/java/index.html[Web] 10 | - link:vertx-web-client/java/index.html[Web client] 11 | - link:vertx-web-api-contract/java/index.html[Web API contracts] 12 | - link:vertx-web-api-service/java/index.html[Web API service] 13 | - link:vertx-web-graphql/java/index.html[Web GraphQL] 14 | - link:vertx-http-proxy/java/index.html[HTTP proxy] 15 | - link:vertx-jdbc-client/java/index.html[JDBC client] 16 | - link:vertx-mongo-client/java/index.html[Mongo client] 17 | - link:vertx-redis-client/java/index.html[Redis client] 18 | - link:vertx-rx/java2/index.html[RxJava2] 19 | - link:vertx-rx/java3/index.html[RxJava3] 20 | - link:vertx-reactive-streams/java/index.html[Reactive streams] 21 | - link:vertx-service-resolver/java/index.html[Service resolver] 22 | - link:vertx-service-discovery/java/index.html[Service discovery] 23 | - link:vertx-circuit-breaker/java/index.html[Circuit breaker] 24 | - link:vertx-config/java/index.html[Config] 25 | - link:vertx-mqtt/java/index.html[MQTT] 26 | - link:vertx-pg-client/java/index.html[PostgreSQL client] 27 | - link:vertx-mssql-client/java/index.html[MS SQL client] 28 | - link:vertx-auth-common/java/index.html[Auth common] 29 | - link:vertx-auth-jwt/java/index.html[JWT auth] 30 | - link:vertx-auth-mongo/java/index.html[Auth MongoDB] 31 | - link:vertx-auth-oauth2/java/index.html[OAuth2] 32 | - link:vertx-auth-htdigest/java/index.html[.htdigest Auth] 33 | - link:vertx-mail-client/java/index.html[Mail client] 34 | - link:vertx-stomp/java/index.html[STOMP] 35 | - link:vertx-consul-client/java/index.html[Consul client] 36 | - link:vertx-cassandra-client/java/index.html[Cassandra client] 37 | - link:vertx-rabbitmq-client/java/index.html[RabbitMQ client] 38 | - link:vertx-kafka-client/java/index.html[Kafka client] 39 | - link:vertx-amqp-bridge/java/index.html[AMQP bridge] 40 | - link:vertx-amqp-client/java/index.html[AMQP client] 41 | - link:vertx-tcp-eventbus-bridge/java/index.html[TCP Eventbus bridge] 42 | - link:vertx-camel-bridge/java/index.html[Camel bridge] 43 | - link:vertx-dropwizard-metrics/java/index.html[Dropwizard metrics] 44 | - link:vertx-micrometer-metrics/java/index.html[Micrometer metrics] 45 | - link:vertx-zipkin/java/index.html[Zipkin] 46 | - link:vertx-opentracing/java/index.html[Opentracing] 47 | - link:vertx-opentelemetry/java/index.html[Opentelemetry] 48 | - link:vertx-health-check/java/index.html[Health check] 49 | - link:vertx-shell/java/index.html[Shell] 50 | - link:vertx-unit/java/index.html[Vert.x unit] 51 | - link:vertx-junit5/java/index.html[Vert.x JUnit 5] 52 | - link:vertx-hazelcast/java/index.html[Hazelcast] 53 | - link:vertx-infinispan/java/index.html[Infinispan] 54 | - link:vertx-ignite/java/index.html[Ignite] 55 | - link:vertx-zookeeper/java/index.html[Apache Zookeeper] 56 | - link:vertx-service-proxy/java/index.html[Service proxies] 57 | - link:vertx-sockjs-service-proxy/java/index.html[SockJS service proxies] 58 | - link:vertx-grpc/java/index.html[gRPC] 59 | 60 | === Kotlin 61 | 62 | - link:vertx-lang-kotlin-coroutines/kotlin/index.html[Kotlin coroutines] 63 | -------------------------------------------------------------------------------- /stack-manager/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 4.0.0 22 | 23 | 24 | io.vertx 25 | vertx-stack 26 | 5.1.0-SNAPSHOT 27 | 28 | 29 | vertx-stack-manager 30 | Vert.x Stack - Stack Manager 31 | 32 | 33 | 1.1.0 34 | ${project.version} 35 | vert.x-${project.version} 36 | 37 | 38 | 39 | 40 | 41 | 42 | commons-logging 43 | commons-logging 44 | 1.2 45 | 46 | 47 | io.vertx 48 | vertx-core 49 | 50 | 51 | io.vertx 52 | vertx-launcher-legacy-cli 53 | 54 | 55 | com.fasterxml.jackson.core 56 | jackson-databind 57 | 58 | 59 | com.fasterxml.jackson.core 60 | jackson-annotations 61 | 62 | 63 | org.apache.maven 64 | maven-aether-provider 65 | 3.3.9 66 | 67 | 68 | org.eclipse.sisu 69 | org.eclipse.sisu.plexus 70 | 71 | 72 | org.codehaus.plexus 73 | plexus-component-annotations 74 | 75 | 76 | 77 | 78 | org.eclipse.aether 79 | aether-api 80 | ${aether.version} 81 | 82 | 83 | org.eclipse.aether 84 | aether-connector-basic 85 | ${aether.version} 86 | 87 | 88 | org.eclipse.aether 89 | aether-transport-file 90 | ${aether.version} 91 | 92 | 93 | org.eclipse.aether 94 | aether-transport-http 95 | ${aether.version} 96 | 97 | 98 | org.slf4j 99 | slf4j-api 100 | 101 | 102 | org.slf4j 103 | jcl-over-slf4j 104 | 105 | 106 | 107 | 108 | org.eclipse.aether 109 | aether-spi 110 | ${aether.version} 111 | 112 | 113 | org.eclipse.aether 114 | aether-impl 115 | ${aether.version} 116 | 117 | 118 | org.eclipse.aether 119 | aether-util 120 | ${aether.version} 121 | 122 | 123 | 124 | com.google.guava 125 | guava 126 | 30.1.1-jre 127 | 128 | 129 | com.jayway.awaitility 130 | awaitility 131 | 1.7.0 132 | test 133 | 134 | 135 | 136 | org.assertj 137 | assertj-core 138 | 3.3.0 139 | test 140 | 141 | 142 | junit 143 | junit 144 | 4.13.1 145 | test 146 | 147 | 148 | 149 | 150 | 151 | 152 | maven-resources-plugin 153 | 154 | 155 | copy-resources 156 | process-resources 157 | 158 | copy-resources 159 | 160 | 161 | \ 162 | ${basedir}/target/vertx-stack 163 | 164 | 165 | src/main/descriptor 166 | true 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | org.apache.maven.plugins 178 | maven-surefire-plugin 179 | 180 | 181 | ${vertx.snapshotRepository} 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /stack-manager/src/main/descriptor/vertx-stack-full.json: -------------------------------------------------------------------------------- 1 | // 2 | // vert.x stack descriptor 3 | // 4 | // To add a dependency: 5 | // - if the dependency is already listed, just set `included` to `true` 6 | // - if not, add the dependency using the Maven coordinates, and set `included` to `true` 7 | // 8 | // You can also set `exclusions` and whether or not the dependency need to resolve its transitive dependencies. 9 | // 10 | // Then launch the resolution process with: vertx resolve --dir=lib --stack=./vertx-vertx.json 11 | // 12 | // To remove a dependency: 13 | // - either remove the dependency declaration or just toggled the `included` value. Then launch the resolution process. 14 | // 15 | { 16 | "variables": { 17 | "vertx.version": "${vertx.version}", 18 | "tcnative.version": "2.0.29.Final" 19 | }, 20 | "dependencies": [ 21 | { 22 | "groupId": "io.vertx", 23 | "artifactId": "vertx-core", 24 | "version": "\${vertx.version}", 25 | "included": true 26 | }, 27 | { 28 | "groupId": "io.vertx", 29 | "artifactId": "vertx-launcher-application", 30 | "version": "\${vertx.version}", 31 | "included": true 32 | }, 33 | { 34 | "groupId": "io.netty", 35 | "artifactId": "netty-tcnative-boringssl-static", 36 | "version": "\${tcnative.version}", 37 | "included": true 38 | }, 39 | { 40 | "groupId": "io.vertx", 41 | "artifactId": "vertx-hazelcast", 42 | "version": "\${vertx.version}", 43 | "included": true 44 | }, 45 | { 46 | "groupId": "io.vertx", 47 | "artifactId": "vertx-lang-groovy", 48 | "version": "\${vertx.version}", 49 | "included": true 50 | }, 51 | { 52 | "groupId": "io.vertx", 53 | "artifactId": "vertx-lang-kotlin", 54 | "version": "\${vertx.version}", 55 | "included": true 56 | }, 57 | { 58 | "groupId": "io.vertx", 59 | "artifactId": "vertx-lang-kotlin-coroutines", 60 | "version": "\${vertx.version}", 61 | "included": true 62 | }, 63 | { 64 | "groupId": "io.vertx", 65 | "artifactId": "vertx-service-proxy", 66 | "version": "\${vertx.version}", 67 | "included": true 68 | }, 69 | { 70 | "groupId": "io.vertx", 71 | "artifactId": "vertx-dropwizard-metrics", 72 | "version": "\${vertx.version}", 73 | "included": true 74 | }, 75 | { 76 | "groupId": "io.vertx", 77 | "artifactId": "vertx-micrometer-metrics", 78 | "version": "\${vertx.version}", 79 | "included": false 80 | }, 81 | { 82 | "groupId": "io.vertx", 83 | "artifactId": "vertx-auth-common", 84 | "version": "\${vertx.version}", 85 | "included": true 86 | }, 87 | { 88 | "groupId": "io.vertx", 89 | "artifactId": "vertx-auth-jwt", 90 | "version": "\${vertx.version}", 91 | "included": true 92 | }, 93 | { 94 | "groupId": "io.vertx", 95 | "artifactId": "vertx-auth-oauth2", 96 | "version": "\${vertx.version}", 97 | "included": true 98 | }, 99 | { 100 | "groupId": "io.vertx", 101 | "artifactId": "vertx-auth-webauthn4j", 102 | "version": "\${vertx.version}", 103 | "included": true 104 | }, 105 | { 106 | "groupId": "io.vertx", 107 | "artifactId": "vertx-auth-otp", 108 | "version": "\${vertx.version}", 109 | "included": true 110 | }, 111 | { 112 | "groupId": "io.vertx", 113 | "artifactId": "vertx-auth-abac", 114 | "version": "\${vertx.version}", 115 | "included": true 116 | }, 117 | { 118 | "groupId": "io.vertx", 119 | "artifactId": "vertx-jdbc-client", 120 | "version": "\${vertx.version}", 121 | "included": true 122 | }, 123 | { 124 | "groupId": "io.vertx", 125 | "artifactId": "vertx-consul-client", 126 | "version": "\${vertx.version}", 127 | "included": true 128 | }, 129 | { 130 | "groupId": "io.vertx", 131 | "artifactId": "vertx-mongo-client", 132 | "version": "\${vertx.version}", 133 | "included": true 134 | }, 135 | { 136 | "groupId": "io.vertx", 137 | "artifactId": "vertx-reactive-streams", 138 | "version": "\${vertx.version}", 139 | "included": true 140 | }, 141 | { 142 | "groupId": "io.vertx", 143 | "artifactId": "vertx-redis-client", 144 | "version": "\${vertx.version}", 145 | "included": true 146 | }, 147 | { 148 | "groupId": "io.vertx", 149 | "artifactId": "vertx-unit", 150 | "version": "\${vertx.version}", 151 | "included": true 152 | }, 153 | { 154 | "groupId": "io.vertx", 155 | "artifactId": "vertx-junit5", 156 | "version": "\${vertx.version}", 157 | "included": true 158 | }, 159 | { 160 | "groupId": "io.vertx", 161 | "artifactId": "vertx-junit5-rx-java2", 162 | "version": "\${vertx.version}", 163 | "included": true 164 | }, 165 | { 166 | "groupId": "io.vertx", 167 | "artifactId": "vertx-web", 168 | "version": "\${vertx.version}", 169 | "included": true 170 | }, 171 | { 172 | "groupId": "io.vertx", 173 | "artifactId": "vertx-web-client", 174 | "version": "\${vertx.version}", 175 | "included": true 176 | }, 177 | { 178 | "groupId": "io.vertx", 179 | "artifactId": "vertx-web-templ-handlebars", 180 | "version": "\${vertx.version}", 181 | "classifier": "shaded", 182 | "transitive": false, 183 | "included": true 184 | }, 185 | { 186 | "groupId": "io.vertx", 187 | "artifactId": "vertx-web-templ-pug", 188 | "version": "\${vertx.version}", 189 | "classifier": "shaded", 190 | "transitive": false, 191 | "included": true 192 | }, 193 | { 194 | "groupId": "io.vertx", 195 | "artifactId": "vertx-web-templ-mvel", 196 | "version": "\${vertx.version}", 197 | "classifier": "shaded", 198 | "transitive": false, 199 | "included": true 200 | }, 201 | { 202 | "groupId": "io.vertx", 203 | "artifactId": "vertx-web-templ-thymeleaf", 204 | "version": "\${vertx.version}", 205 | "classifier": "shaded", 206 | "transitive": false, 207 | "included": true 208 | }, 209 | { 210 | "groupId": "io.vertx", 211 | "artifactId": "vertx-sockjs-service-proxy", 212 | "version": "\${vertx.version}", 213 | "included": false 214 | }, 215 | { 216 | "groupId": "io.vertx", 217 | "artifactId": "vertx-mail-client", 218 | "version": "\${vertx.version}", 219 | "included": true 220 | }, 221 | { 222 | "groupId": "io.vertx", 223 | "artifactId": "vertx-stomp", 224 | "version": "\${vertx.version}", 225 | "included": true 226 | }, 227 | { 228 | "groupId": "io.vertx", 229 | "artifactId": "vertx-shell", 230 | "version": "\${vertx.version}", 231 | "included": false 232 | }, 233 | { 234 | "groupId": "io.vertx", 235 | "artifactId": "vertx-tcp-eventbus-bridge", 236 | "version": "\${vertx.version}", 237 | "included": true 238 | }, 239 | { 240 | "groupId": "io.vertx", 241 | "artifactId": "vertx-infinispan", 242 | "version": "\${vertx.version}", 243 | "included": false 244 | }, 245 | { 246 | "groupId": "io.vertx", 247 | "artifactId": "vertx-hazelcast", 248 | "version": "\${vertx.version}", 249 | "included": false 250 | }, 251 | { 252 | "groupId": "io.vertx", 253 | "artifactId": "vertx-camel-bridge", 254 | "version": "\${vertx.version}", 255 | "included": false 256 | }, 257 | { 258 | "groupId": "io.vertx", 259 | "artifactId": "vertx-service-discovery", 260 | "version": "\${vertx.version}", 261 | "included": true 262 | }, 263 | { 264 | "groupId": "io.vertx", 265 | "artifactId": "vertx-service-discovery-bridge-kubernetes", 266 | "version": "\${vertx.version}", 267 | "included": false 268 | }, 269 | { 270 | "groupId": "io.vertx", 271 | "artifactId": "vertx-service-discovery-bridge-docker", 272 | "version": "\${vertx.version}", 273 | "included": false 274 | }, 275 | { 276 | "groupId": "io.vertx", 277 | "artifactId": "vertx-service-discovery-bridge-docker-links", 278 | "version": "\${vertx.version}", 279 | "included": false 280 | }, 281 | { 282 | "groupId": "io.vertx", 283 | "artifactId": "vertx-service-discovery-bridge-consul", 284 | "version": "\${vertx.version}", 285 | "included": false 286 | }, 287 | { 288 | "groupId": "io.vertx", 289 | "artifactId": "vertx-service-discovery-backend-redis", 290 | "version": "\${vertx.version}", 291 | "included": false 292 | }, 293 | { 294 | "groupId": "io.vertx", 295 | "artifactId": "vertx-config", 296 | "version": "\${vertx.version}", 297 | "included": true 298 | }, 299 | { 300 | "groupId": "io.vertx", 301 | "artifactId": "vertx-config-git", 302 | "version": "\${vertx.version}", 303 | "included": false 304 | }, 305 | { 306 | "groupId": "io.vertx", 307 | "artifactId": "vertx-config-hocon", 308 | "version": "\${vertx.version}", 309 | "included": false 310 | }, 311 | { 312 | "groupId": "io.vertx", 313 | "artifactId": "vertx-config-kubernetes-configmap", 314 | "version": "\${vertx.version}", 315 | "included": false 316 | }, 317 | { 318 | "groupId": "io.vertx", 319 | "artifactId": "vertx-config-redis", 320 | "version": "\${vertx.version}", 321 | "included": false 322 | }, 323 | { 324 | "groupId": "io.vertx", 325 | "artifactId": "vertx-config-spring-config-server", 326 | "version": "\${vertx.version}", 327 | "included": false 328 | }, 329 | { 330 | "groupId": "io.vertx", 331 | "artifactId": "vertx-config-vault", 332 | "version": "\${vertx.version}", 333 | "included": false 334 | }, 335 | { 336 | "groupId": "io.vertx", 337 | "artifactId": "vertx-config-consul", 338 | "version": "\${vertx.version}", 339 | "included": false 340 | }, 341 | { 342 | "groupId": "io.vertx", 343 | "artifactId": "vertx-config-yaml", 344 | "version": "\${vertx.version}", 345 | "included": false 346 | }, 347 | { 348 | "groupId": "io.vertx", 349 | "artifactId": "vertx-config-zookeeper", 350 | "version": "\${vertx.version}", 351 | "included": false 352 | }, 353 | { 354 | "groupId": "io.vertx", 355 | "artifactId": "vertx-circuit-breaker", 356 | "version": "\${vertx.version}", 357 | "included": true 358 | }, 359 | { 360 | "groupId": "io.vertx", 361 | "artifactId": "vertx-rabbitmq-client", 362 | "version": "\${vertx.version}", 363 | "included": true 364 | }, 365 | { 366 | "groupId": "io.vertx", 367 | "artifactId": "vertx-kafka-client", 368 | "version": "\${vertx.version}", 369 | "included": false 370 | }, 371 | { 372 | "groupId": "io.vertx", 373 | "artifactId": "vertx-consul-client", 374 | "version": "\${vertx.version}", 375 | "included": false 376 | }, 377 | { 378 | "groupId": "io.vertx", 379 | "artifactId": "vertx-mqtt", 380 | "version": "\${vertx.version}", 381 | "included": false 382 | }, 383 | { 384 | "groupId": "io.vertx", 385 | "artifactId": "vertx-grpc-common", 386 | "version": "\${vertx.version}", 387 | "included": false 388 | }, 389 | { 390 | "groupId": "io.vertx", 391 | "artifactId": "vertx-grpc-client", 392 | "version": "\${vertx.version}", 393 | "included": false 394 | }, 395 | { 396 | "groupId": "io.vertx", 397 | "artifactId": "vertx-grpc-server", 398 | "version": "\${vertx.version}", 399 | "included": false 400 | }, 401 | { 402 | "groupId": "io.vertx", 403 | "artifactId": "vertx-json-schema", 404 | "version": "\${vertx.version}", 405 | "included": false 406 | }, 407 | { 408 | "groupId": "io.vertx", 409 | "artifactId": "vertx-openapi", 410 | "version": "\${vertx.version}", 411 | "included": false 412 | }, 413 | { 414 | "groupId": "io.vertx", 415 | "artifactId": "vertx-web-openapi-router", 416 | "version": "\${vertx.version}", 417 | "included": false 418 | } 419 | ] 420 | } 421 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/command/ResolveCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.command; 18 | 19 | import io.vertx.core.cli.CLI; 20 | import io.vertx.core.cli.CLIException; 21 | import io.vertx.core.cli.CommandLine; 22 | import io.vertx.core.cli.annotations.*; 23 | import io.vertx.core.spi.launcher.DefaultCommand; 24 | import io.vertx.core.spi.launcher.ExecutionContext; 25 | import io.vertx.stack.model.Stack; 26 | import io.vertx.stack.model.StackResolution; 27 | import io.vertx.stack.model.StackResolutionOptions; 28 | import io.vertx.stack.utils.Home; 29 | 30 | import java.io.File; 31 | import java.util.Arrays; 32 | import java.util.List; 33 | 34 | /** 35 | * The resolve command. 36 | *

37 | * The resolve command maintains the files contained in the `lib` directory of a vert.x stack based on a stack 38 | * descriptor. 39 | * 40 | * @author Clement Escoffier 41 | */ 42 | @Name("resolve") 43 | @Summary("Resolve the vert.x stack according to the content the stack description.") 44 | @Description("Synchronize the content of a vert.x distribution based on the description given in a 'json' file. From " + 45 | "the 'VERTX_HOME' directory, launch it with: 'bin/vertx resolve'.") 46 | public class ResolveCommand extends DefaultCommand { 47 | 48 | private String directory; 49 | private String descriptor; 50 | private boolean failOnConflict; 51 | private String localRepository; 52 | private List remoteRepositories; 53 | private String httpProxy; 54 | private String httpsProxy; 55 | private boolean disableCache; 56 | private boolean disableCacheForSnapshots; 57 | private File cacheFile; 58 | 59 | @Option(longName = "dir") 60 | @Description("The directory containing the artifacts composing the stack. Defaults to the '$VERTX_HOME/lib' " + 61 | "directory, if $VERTX_HOME is set, './lib' otherwise.") 62 | public void setDirectory(String file) { 63 | this.directory = file; 64 | } 65 | 66 | @Argument(index = 0, required = false, argName = "stack-descriptor") 67 | @DefaultValue("vertx-stack.json") 68 | @Description("The path to the stack descriptor. Defaults to '$VERTX_HOME/vertx-stack.json', if $VERTX_HOME is set, " + 69 | "'./vertx-stack.json' otherwise.") 70 | public void setStackDescriptor(String file) { 71 | this.descriptor = file; 72 | } 73 | 74 | @Option(longName = "fail-on-conflict", flag = true) 75 | @DefaultValue("false") 76 | @Description("Set whether or not the resolver should fail or conflict or just log a warning. Disabled by default.") 77 | public void setFailOnConflict(boolean fail) { 78 | this.failOnConflict = fail; 79 | } 80 | 81 | @Option(longName = "local-repo") 82 | @Description("Set the path to the local Maven repository. Defaults to '~/.m2/repository'.") 83 | public void setLocalRepository(String localRepository) { 84 | this.localRepository = localRepository; 85 | } 86 | 87 | @Option(longName = "remote-repo", acceptMultipleValues = true) 88 | @Description("Set the path to a remote Maven repository. Can be set multiple times.") 89 | public void setRemoteRepositories(List remoteRepositories) { 90 | this.remoteRepositories = remoteRepositories; 91 | } 92 | 93 | @Option(longName = "http-proxy") 94 | @Description("Set the HTTP proxy address if any.") 95 | public void setHttpProxy(String p) { 96 | this.httpProxy = p; 97 | } 98 | 99 | @Option(longName = "https-proxy") 100 | @Description("Set the HTTPS proxy address if any.") 101 | public void setHttpsProxy(String p) { 102 | this.httpsProxy = p; 103 | } 104 | 105 | @Option(longName = "no-cache", flag = true) 106 | @Description("Disable the resolver cache") 107 | public void setDisableCache(boolean disableCache) { 108 | this.disableCache = disableCache; 109 | } 110 | 111 | @Option(longName = "no-cache-for-snapshots", flag = true) 112 | @Description("Disable the caching of snapshot resolution") 113 | public void setDisableCacheForSnapshots(boolean disableCache) { 114 | this.disableCacheForSnapshots = disableCache; 115 | } 116 | 117 | @Option(longName = "cache-file") 118 | @Hidden 119 | public void setCacheLocation(File cache) { 120 | this.cacheFile = cache; 121 | } 122 | 123 | /** 124 | * Executes the command. 125 | * @throws CLIException if something bad happened during the execution. 126 | */ 127 | @Override 128 | public void run() throws CLIException { 129 | File descriptorFile = new File(descriptor); 130 | if (! descriptorFile.isFile()) { 131 | // Try with vert.x home 132 | if (Home.getVertxHome() != null) { 133 | descriptorFile = new File(Home.getVertxHome(), descriptor); 134 | } 135 | } 136 | 137 | if (! descriptorFile.isFile()) { 138 | String message = "Cannot find the stack descriptor. Have been tried: \n\t - ./" + descriptorFile; 139 | if (Home.getVertxHome() != null) { 140 | message += "\n\t - " + descriptorFile.getAbsolutePath(); 141 | } 142 | throw new CLIException(message); 143 | } 144 | 145 | File lib; 146 | if (directory == null) { 147 | if (Home.getVertxHome() != null) { 148 | lib = new File(Home.getVertxHome(), "lib"); 149 | } else { 150 | lib = new File("lib"); 151 | } 152 | } else { 153 | lib = new File(directory); 154 | } 155 | 156 | out().println("lib directory set to: " + lib.getAbsolutePath()); 157 | 158 | Stack stack = Stack.fromDescriptor(descriptorFile); 159 | StackResolutionOptions options = new StackResolutionOptions() 160 | .setFailOnConflicts(failOnConflict) 161 | .setCacheDisabled(disableCache) 162 | .setCacheDisabledForSnapshots(disableCacheForSnapshots) 163 | .setCacheFile(cacheFile); 164 | 165 | if (localRepository != null) { 166 | options.setLocalRepository(localRepository); 167 | } 168 | 169 | if (remoteRepositories != null) { 170 | options.setRemoteRepositories(remoteRepositories); 171 | } 172 | 173 | options.setHttpProxy(httpProxy); 174 | options.setHttpsProxy(httpsProxy); 175 | 176 | StackResolution resolution = new StackResolution(stack, lib, options); 177 | resolution.resolve(); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/command/ResolveCommandFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.command; 18 | 19 | import io.vertx.core.spi.launcher.DefaultCommandFactory; 20 | 21 | /** 22 | * The {@link ResolveCommand} factory. 23 | * 24 | * @author Clement Escoffier 25 | */ 26 | public class ResolveCommandFactory extends DefaultCommandFactory { 27 | 28 | public ResolveCommandFactory() { 29 | super(ResolveCommand.class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/command/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.command; 18 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/Artifact.java: -------------------------------------------------------------------------------- 1 | package io.vertx.stack.model; 2 | 3 | import org.eclipse.aether.artifact.AbstractArtifact; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.Objects; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | public class Artifact extends AbstractArtifact { 13 | 14 | private final String groupId; 15 | private final String artifactId; 16 | private final String version; 17 | private final String classifier; 18 | private final String extension; 19 | private final File file; 20 | private final Map properties; 21 | private final Artifact via; 22 | private static final Pattern coordinatesPattern = 23 | Pattern.compile("([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)"); 24 | 25 | public Artifact(String coordinates) { 26 | this(coordinates, null); 27 | } 28 | 29 | public Artifact(String groupId, String artifactId, String classifier, String extension, String version, Artifact via) { 30 | this(groupId + ":" + artifactId + ":" + extension + ":" + classifier + ":" + version, via); 31 | } 32 | 33 | public Artifact(String groupId, String artifactId, String extension, String version, Artifact via) { 34 | this(groupId + ":" + artifactId + ":" + extension + ":" + version, via); 35 | } 36 | 37 | public Artifact(org.eclipse.aether.artifact.Artifact fromArtifact, Artifact via) { 38 | this(coordinates(fromArtifact), via, fromArtifact.getFile(), fromArtifact.getProperties()); 39 | } 40 | 41 | public Artifact(String coordinates, Artifact viaArtifact) { 42 | this(coordinates, viaArtifact, null, new HashMap<>()); 43 | } 44 | 45 | private Artifact(String coordinates, Artifact viaArtifact, File artifactFile, Map props) { 46 | Matcher m = coordinatesPattern.matcher(coordinates); 47 | 48 | if (!m.matches()) { 49 | throw new IllegalArgumentException("Bad artifact coordinates " + coordinates 50 | + ", expected format is :[:[:]]:"); 51 | } 52 | 53 | groupId = m.group(1); 54 | artifactId = m.group(2); 55 | extension = defaultIfEmpty(m.group(4), "jar"); 56 | classifier = defaultIfEmpty(m.group(6), ""); 57 | version = m.group(7); 58 | file = artifactFile; 59 | properties = copyProperties(props); 60 | via = viaArtifact; 61 | } 62 | 63 | private String defaultIfEmpty(String value, String defaultValue) { 64 | if (value == null || value.trim().isEmpty()) { 65 | return defaultValue; 66 | } else { 67 | return value; 68 | } 69 | } 70 | 71 | @Override 72 | public String getGroupId() { 73 | return groupId; 74 | } 75 | 76 | @Override 77 | public String getArtifactId() { 78 | return artifactId; 79 | } 80 | 81 | @Override 82 | public String getVersion() { 83 | return version; 84 | } 85 | 86 | @Override 87 | public String getClassifier() { 88 | return classifier; 89 | } 90 | 91 | @Override 92 | public String getExtension() { 93 | return extension; 94 | } 95 | 96 | @Override 97 | public Artifact setFile(File file) { 98 | if (Objects.equals(this.file, file)) { 99 | return this; 100 | } else { 101 | return new Artifact(coordinates(this), via, file, properties); 102 | } 103 | } 104 | 105 | @Override 106 | public File getFile() { 107 | return file; 108 | } 109 | 110 | @Override 111 | public Map getProperties() { 112 | return properties; 113 | } 114 | 115 | @Override 116 | public Artifact setProperties(Map properties) { 117 | if (Objects.equals(this.properties, properties)) { 118 | return this; 119 | } else { 120 | return new Artifact(coordinates(this), via, file, copyProperties(properties)); 121 | } 122 | } 123 | 124 | public Artifact getVia() { 125 | return via; 126 | } 127 | 128 | public String getCoordinates() { 129 | return coordinates(this); 130 | } 131 | 132 | @Override 133 | public boolean equals(Object o) { 134 | if (this == o) return true; 135 | if (o == null || getClass() != o.getClass()) return false; 136 | if (!super.equals(o)) return false; 137 | Artifact artifact = (Artifact) o; 138 | return Objects.equals(groupId, artifact.groupId) 139 | && Objects.equals(artifactId, artifact.artifactId) 140 | && Objects.equals(version, artifact.version) 141 | && Objects.equals(classifier, artifact.classifier) 142 | && Objects.equals(extension, artifact.extension) 143 | && Objects.equals(file, artifact.file) 144 | && Objects.equals(properties, artifact.properties) 145 | && Objects.equals(via, artifact.via); 146 | } 147 | 148 | @Override 149 | public int hashCode() { 150 | return Objects.hash(super.hashCode(), groupId, artifactId, version, classifier, extension, file, properties, via); 151 | } 152 | 153 | private static String coordinates(org.eclipse.aether.artifact.Artifact artifact) { 154 | // :[:[:]]: 155 | return artifact.getGroupId() + ":" + artifact.getArtifactId() 156 | + ":" + artifact.getExtension() 157 | + (artifact.getClassifier().isEmpty() ? "" : ":" + artifact.getClassifier()) 158 | + ":" + artifact.getVersion(); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/Dependency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonIgnore; 20 | import io.vertx.stack.resolver.ResolutionOptions; 21 | import org.apache.maven.model.Exclusion; 22 | 23 | /** 24 | * Represents a dependency. The stack describes a set of dependencies resolved as Maven dependencies. Each dependency 25 | * can be included or excluded and can instruct whether the resolution need to bring the transitive dependencies too. 26 | *

27 | * Be aware the dependencies cannot be set as "optional', as optionality do not make sense when we deploy the artifact. 28 | * 29 | * @author Clement Escoffier 30 | */ 31 | public class Dependency extends org.apache.maven.model.Dependency { 32 | 33 | private boolean included = true; 34 | 35 | private boolean transitive = true; 36 | 37 | /** 38 | * Creates a new {@link Dependency}. 39 | * 40 | * @param groupId the groupId 41 | * @param artifactId the artifactId 42 | * @param version the version 43 | */ 44 | public Dependency(String groupId, String artifactId, String version) { 45 | this(); 46 | setGroupId(groupId); 47 | setArtifactId(artifactId); 48 | setVersion(version); 49 | } 50 | 51 | /** 52 | * Creates a new {@link Dependency}. 53 | * 54 | * @param groupId the groupId 55 | * @param artifactId the artifactId 56 | * @param version the version 57 | * @param type the type / extension / packaging 58 | */ 59 | public Dependency(String groupId, String artifactId, String version, String type) { 60 | this(groupId, artifactId, version); 61 | setType(type); 62 | } 63 | 64 | /** 65 | * Creates a new {@link Dependency}. 66 | *

67 | * The type is set to "jar" by default. 68 | */ 69 | public Dependency() { 70 | setType("jar"); 71 | } 72 | 73 | /** 74 | * @return {@code true} if the dependency is included, {@code false} otherwise. 75 | */ 76 | public boolean isIncluded() { 77 | return included; 78 | } 79 | 80 | /** 81 | * Sets whether or not the dependency is included. Included by default. 82 | * 83 | * @return the current {@link Dependency} instance. 84 | */ 85 | public Dependency setIncluded(boolean included) { 86 | this.included = included; 87 | return this; 88 | } 89 | 90 | /** 91 | * @return {@code true} if the dependency must be resolved with its transitive dependencies. 92 | */ 93 | public boolean isTransitive() { 94 | return transitive; 95 | } 96 | 97 | /** 98 | * Sets whether or not the dependency resolution also resolves the transitive dependencies. Transitive dependencies 99 | * are resolved by default. 100 | * 101 | * @return the current {@link Dependency} instance. 102 | */ 103 | public Dependency setTransitive(boolean transitive) { 104 | this.transitive = transitive; 105 | return this; 106 | } 107 | 108 | /** 109 | * Creates the {@link ResolutionOptions} object for the dependency. 110 | * 111 | * @return the {@link ResolutionOptions} instructing the dependency resolution. 112 | */ 113 | public ResolutionOptions getResolutionOptions() { 114 | ResolutionOptions options = new ResolutionOptions(); 115 | options.setWithTransitive(transitive); 116 | for (Exclusion exclusion : getExclusions()) { 117 | options.addExclusion(exclusion.getGroupId() + ":" + exclusion.getArtifactId()); 118 | } 119 | 120 | return options; 121 | } 122 | 123 | /** 124 | * @return the Maven GACV string. 125 | */ 126 | public String getGACV() { 127 | return getManagementKey() + ":" + getVersion(); 128 | } 129 | 130 | /** 131 | * Not supported property, as the concept of 'optional' does not make sense when building a stack. 132 | * 133 | * @param optional ignored 134 | */ 135 | @Override 136 | @JsonIgnore 137 | public void setOptional(boolean optional) { 138 | throw new UnsupportedOperationException("You cannot add an optional dependency to a stack - optional does not " + 139 | "make sense in this case"); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/DependencyConflictException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.model; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.concurrent.atomic.AtomicInteger; 24 | 25 | /** 26 | * Thrown when a conflict is detected between two dependencies. 27 | * 28 | * @author Clement Escoffier 29 | */ 30 | public class DependencyConflictException extends RuntimeException { 31 | 32 | private final String artifact; 33 | private final String version; 34 | private final List trace; 35 | private final String conflictingDependency; 36 | private final Artifact conflictingArtifact; 37 | 38 | /** 39 | * Creates a {@link DependencyConflictException}. 40 | * 41 | * @param artifact the artifact 42 | * @param version the current version 43 | * @param conflictingDependency the conflicting dependency 44 | * @param conflictingArtifact the conflicting {@link Artifact} 45 | */ 46 | public DependencyConflictException(String artifact, String version, List trace, String conflictingDependency, Artifact conflictingArtifact) { 47 | this.artifact = artifact; 48 | this.version = version; 49 | this.trace = trace; 50 | this.conflictingDependency = conflictingDependency; 51 | this.conflictingArtifact = conflictingArtifact; 52 | } 53 | 54 | /** 55 | * Returns the detail message string of this throwable. 56 | * 57 | * @return the detail message string of this {@code Throwable} instance 58 | * (which may be {@code null}). 59 | */ 60 | @Override 61 | public String getMessage() { 62 | 63 | return "Conflict detected for artifact " + artifact + " - version " + version + " was already selected" + 64 | " by " + trace + 65 | " while " + conflictingDependency + " depends on version " + conflictingArtifact.getVersion() + 66 | " - see the following chain:\n" + 67 | renderArtifactChain(conflictingArtifact, new ArrayList<>()); 68 | } 69 | 70 | private String renderArtifactChain(Artifact fromArtifact, List acc) { 71 | if (fromArtifact.getVia() == null) { 72 | StringBuilder resultBuilder = new StringBuilder(fromArtifact.getCoordinates()); 73 | AtomicInteger level = new AtomicInteger(0); 74 | acc.forEach(coords -> { 75 | String indent = StringUtils.repeat('\t', level.incrementAndGet()); 76 | resultBuilder.append("\n") 77 | .append(indent).append("\\-- ").append(coords); 78 | }); 79 | return resultBuilder.toString(); 80 | } else { 81 | acc.add(0, fromArtifact.getCoordinates()); 82 | return renderArtifactChain(fromArtifact.getVia(), acc); 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/Stack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.model; 18 | 19 | import com.fasterxml.jackson.core.JsonParser; 20 | import com.fasterxml.jackson.databind.ObjectMapper; 21 | import io.vertx.stack.utils.Filtering; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.util.ArrayList; 26 | import java.util.LinkedHashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | import java.util.stream.Stream; 30 | 31 | /** 32 | * Represents a stack. A stack is composed by a set of dependencies and variables. 33 | * 34 | * @author Clement Escoffier 35 | */ 36 | public class Stack { 37 | 38 | private List dependencies = new ArrayList<>(); 39 | 40 | private Map variables = new LinkedHashMap<>(); 41 | 42 | /** 43 | * Adds a new variables or updates the value of an existing one. 44 | * 45 | * @param key the variable name 46 | * @param value the value 47 | * @return the current {@link Stack} instance 48 | */ 49 | public Stack addVariable(String key, String value) { 50 | variables.put(key, value); 51 | return this; 52 | } 53 | 54 | /** 55 | * Removes a variable. 56 | * 57 | * @param key the variable name 58 | * @return the current {@link Stack} instance 59 | */ 60 | public Stack removeVariable(String key) { 61 | variables.remove(key); 62 | return this; 63 | } 64 | 65 | /** 66 | * Adds a dependency. 67 | * 68 | * @param dependency the dependency 69 | * @return the current {@link Stack} instance 70 | */ 71 | public Stack addDependency(Dependency dependency) { 72 | dependencies.add(dependency); 73 | return this; 74 | } 75 | 76 | /** 77 | * Removes a dependency. 78 | * 79 | * @param dependency the dependency 80 | * @return the current {@link Stack} instance 81 | */ 82 | public Stack removeDependency(Dependency dependency) { 83 | dependencies.remove(dependency); 84 | return this; 85 | } 86 | 87 | /** 88 | * Gets the variables. 89 | * 90 | * @return the variables, empty if none. 91 | */ 92 | public Map getVariables() { 93 | return variables; 94 | } 95 | 96 | /** 97 | * Apply filtering on the set of dependencies. 98 | */ 99 | public void applyFiltering() { 100 | // Compute the final set of properties. 101 | // First the properties, Then the system properties, so you can override a value using -D. 102 | Map properties = new LinkedHashMap<>(); 103 | properties.putAll(variables); 104 | properties.putAll((Map) System.getProperties()); 105 | 106 | dependencies.stream().forEach(dependency -> { 107 | dependency.setGroupId(Filtering.filter(dependency.getGroupId(), properties)); 108 | dependency.setArtifactId(Filtering.filter(dependency.getArtifactId(), properties)); 109 | dependency.setVersion(Filtering.filter(dependency.getVersion(), properties)); 110 | dependency.setClassifier(Filtering.filter(dependency.getClassifier(), properties)); 111 | dependency.setType(Filtering.filter(dependency.getType(), properties)); 112 | }); 113 | } 114 | 115 | /** 116 | * Gets the dependencies, empty if none. 117 | * 118 | * @return the dependencies 119 | */ 120 | public Stream getDependencies() { 121 | return dependencies.stream(); 122 | } 123 | 124 | /** 125 | * Reads a stack descriptor. 126 | * 127 | * @param descriptor the descriptor, must be a valid YAML file. 128 | * @return the created stack 129 | */ 130 | public static Stack fromDescriptor(File descriptor) { 131 | ObjectMapper mapper = new ObjectMapper(); 132 | mapper = mapper 133 | .enable(JsonParser.Feature.ALLOW_COMMENTS) 134 | .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES) 135 | .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES) 136 | .enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION); 137 | try { 138 | return mapper.readValue(descriptor, Stack.class); 139 | } catch (IOException e) { 140 | throw new IllegalArgumentException("Cannot load stack from " + descriptor.getAbsolutePath(), e); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/StackResolution.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.model; 18 | 19 | import io.vertx.core.internal.logging.Logger; 20 | import io.vertx.core.internal.logging.LoggerFactory; 21 | import io.vertx.stack.resolver.Resolver; 22 | import io.vertx.stack.utils.Actions; 23 | import io.vertx.stack.utils.Cache; 24 | import org.eclipse.aether.artifact.Artifact; 25 | 26 | import java.io.File; 27 | import java.nio.file.Path; 28 | import java.util.*; 29 | import java.util.function.Predicate; 30 | import java.util.stream.Collectors; 31 | 32 | /** 33 | * Object responsible for resolving a stack. This object is stateful, and must be used only for a single resolution. 34 | * 35 | * @author Clement Escoffier 36 | */ 37 | public class StackResolution { 38 | 39 | private final static Logger LOGGER = LoggerFactory.getLogger("Stack Resolution"); 40 | 41 | private final File directory; 42 | private final Stack stack; 43 | 44 | private final Map selectedVersions = new LinkedHashMap<>(); 45 | private final Map selectedArtifacts = new LinkedHashMap<>(); 46 | 47 | /** 48 | * Map keeping a trace from who has resolved which version. It imrpvoes the reporting when a conflict has been 49 | * detected. 50 | */ 51 | private final Map> traces = new LinkedHashMap<>(); 52 | 53 | private final StackResolutionOptions options; 54 | private Resolver resolver; 55 | 56 | private final Cache cache; 57 | 58 | /** 59 | * Creates an instance of {@link StackResolution}. 60 | * 61 | * @param stack the stack 62 | * @param directory the output directory, created if not existing 63 | * @param options the stack resolution options 64 | */ 65 | public StackResolution(Stack stack, File directory, StackResolutionOptions options) { 66 | Objects.requireNonNull(stack); 67 | Objects.requireNonNull(options); 68 | Objects.requireNonNull(directory); 69 | this.stack = stack; 70 | this.options = options; 71 | this.directory = directory; 72 | this.cache = new Cache(options.isCacheDisabled(), options.isCacheDisabledForSnapshots(), options.getCacheFile()); 73 | } 74 | 75 | /** 76 | * Resolves the stack. 77 | * 78 | * @return the map artifact's management key - file composing the stack 79 | */ 80 | public Map resolve() { 81 | traces.clear(); 82 | selectedVersions.clear(); 83 | init(); 84 | stack.getDependencies().forEach(this::resolve); 85 | List chain = computeChainOfActions(); 86 | 87 | chain.forEach(Actions.Action::execute); 88 | 89 | Map resolved = new LinkedHashMap<>(); 90 | for (ResolvedArtifact artifact : selectedArtifacts.values()) { 91 | Path source = artifact.artifact.getFile().toPath(); 92 | Path output = directory.toPath().resolve(source.getFileName()); 93 | resolved.put(artifact.artifact.toString(), output.toFile()); 94 | } 95 | 96 | return resolved; 97 | } 98 | 99 | public Map resolve(Predicate validator) { 100 | traces.clear(); 101 | selectedVersions.clear(); 102 | init(); 103 | stack.getDependencies().forEach(this::resolve); 104 | List chain = computeChainOfActions(); 105 | 106 | chain.forEach(Actions.Action::execute); 107 | 108 | Map resolved = new LinkedHashMap<>(); 109 | for (ResolvedArtifact artifact : selectedArtifacts.values()) { 110 | String gav = artifact.artifact.toString(); 111 | if (!validator.test(gav)) { 112 | throw new IllegalStateException("Invalid artifact " + gav + ", used by " + artifact.getUsages()); 113 | } 114 | Path source = artifact.artifact.getFile().toPath(); 115 | Path output = directory.toPath().resolve(source.getFileName()); 116 | resolved.put(gav, output.toFile()); 117 | } 118 | 119 | return resolved; 120 | } 121 | 122 | private void init() { 123 | if (!directory.isDirectory()) { 124 | LOGGER.info("Creating directory " + directory.getAbsolutePath()); 125 | boolean mkdirs = directory.mkdirs(); 126 | LOGGER.debug("Directory created: " + mkdirs); 127 | } 128 | stack.applyFiltering(); 129 | stack.getDependencies().filter(Dependency::isIncluded).forEach( 130 | dependency -> selectedVersions.put(dependency.getManagementKey(), dependency.getVersion())); 131 | resolver = Resolver.create(options); 132 | } 133 | 134 | private List computeChainOfActions() { 135 | File[] files = directory.listFiles((dir, name) -> name.endsWith(".jar")); 136 | if (files == null) { 137 | throw new IllegalStateException("Unable to read from the file system"); 138 | } 139 | 140 | Map marks = new HashMap<>(); 141 | for (File file : files) { 142 | marks.put(file.getName(), false); 143 | } 144 | 145 | List chain = new ArrayList<>(); 146 | 147 | selectedArtifacts.forEach((key, artifact) -> { 148 | String fileName = artifact.getArtifact().getFile().getName(); 149 | 150 | if (marks.containsKey(fileName)) { 151 | // Mark the file. 152 | marks.put(fileName, true); 153 | chain.add(Actions.skip(artifact.getArtifact())); 154 | } else { 155 | chain.add(Actions.copy(artifact.getArtifact(), directory)); 156 | } 157 | }); 158 | 159 | // Schedule the deletion of all non-marked file. 160 | marks.forEach((fileName, mark) -> { 161 | if (!mark && !fileName.startsWith("vertx-stack-manager-")) { // Do not delete me 162 | chain.add(Actions.remove(new File(directory, fileName))); 163 | } 164 | }); 165 | 166 | return chain; 167 | } 168 | 169 | private void resolve(Dependency dependency) { 170 | List list; 171 | if (dependency.isIncluded()) { 172 | list = cache.get(dependency.getGACV(), dependency.getResolutionOptions()); 173 | // artifacts = cache.get(dependency.getGACV(), dependency.getResolutionOptions()); 174 | if (list == null || list.isEmpty()) { 175 | // list = resolver.resolve(dependency.getGACV(), dependency.getResolutionOptions()); 176 | list = resolver.resolve(dependency.getGACV(), dependency.getResolutionOptions()); 177 | cache.put(dependency.getGACV(), dependency.getResolutionOptions(), list); 178 | cache.writeCacheOnFile(); 179 | } else { 180 | LOGGER.info("Dependency " + dependency + " loaded from cache"); 181 | } 182 | } else { 183 | return; 184 | } 185 | 186 | if (list == null || list.isEmpty()) { 187 | throw new IllegalArgumentException("Cannot resolve " + dependency); 188 | } 189 | 190 | LOGGER.debug("Artifacts resolved for " + dependency.getGACV() + " : " 191 | + list.stream().map(Object::toString).collect(Collectors.toList())); 192 | 193 | list.forEach(artifact -> { 194 | String gaec = getManagementKey(artifact); 195 | String version = selectedVersions.get(gaec); 196 | if (version == null || version.equalsIgnoreCase(artifact.getBaseVersion())) { 197 | selectedVersions.put(gaec, artifact.getBaseVersion()); 198 | keepATrace(dependency, artifact); 199 | } else { 200 | List trace = traces.get(gaec + ":" + version); 201 | if (options.isFailOnConflicts()) { 202 | throw new DependencyConflictException(gaec, version, trace, dependency.getGACV(), artifact); 203 | } 204 | } 205 | addSelectedArtifact(dependency, artifact, version); 206 | }); 207 | } 208 | 209 | /** 210 | * Keep a trace of the resolution. 211 | * 212 | * @param dependency the dependency having triggered the resolution 213 | * @param artifact the resolved artifact 214 | */ 215 | private void keepATrace(Dependency dependency, Artifact artifact) { 216 | String traceId = getManagementKey(artifact) + ":" + artifact.getBaseVersion(); 217 | List deps = traces.computeIfAbsent(traceId, k -> new ArrayList<>()); 218 | deps.add(dependency.getGACV()); 219 | } 220 | 221 | private void addSelectedArtifact(Dependency dependency, Artifact artifact, String version) { 222 | String key = getManagementKey(artifact); 223 | ResolvedArtifact resolved = selectedArtifacts.get(key); 224 | if (resolved != null) { 225 | resolved.addUsage(getManagementKey(dependency)); 226 | } else { 227 | selectedArtifacts.put(key, 228 | new ResolvedArtifact().addUsage(getManagementKey(dependency)) 229 | .setSelectedVersion(version).setArtifact(artifact)); 230 | } 231 | } 232 | 233 | private String getManagementKey(Artifact artifact) { 234 | return artifact.getGroupId() 235 | + ":" + artifact.getArtifactId() 236 | + ":" + artifact.getExtension() 237 | + (artifact.getClassifier() != null && !artifact.getClassifier().isEmpty() 238 | ? ":" + artifact.getClassifier() : ""); 239 | } 240 | 241 | private String getManagementKey(Dependency dependency) { 242 | return dependency.getManagementKey(); 243 | } 244 | 245 | /** 246 | * Represents a resolved artifact. 247 | */ 248 | public static class ResolvedArtifact { 249 | private Artifact artifact; 250 | private String selectedVersion; 251 | private final Set usages = new LinkedHashSet<>(); 252 | 253 | public Artifact getArtifact() { 254 | return artifact; 255 | } 256 | 257 | public ResolvedArtifact setArtifact(Artifact artifact) { 258 | this.artifact = artifact; 259 | return this; 260 | } 261 | 262 | @SuppressWarnings("unused") 263 | public String getSelectedVersion() { 264 | return selectedVersion; 265 | } 266 | 267 | public ResolvedArtifact setSelectedVersion(String selectedVersion) { 268 | this.selectedVersion = selectedVersion; 269 | return this; 270 | } 271 | 272 | public ResolvedArtifact addUsage(String key) { 273 | usages.add(key); 274 | return this; 275 | } 276 | 277 | @SuppressWarnings("unused") 278 | public Set getUsages() { 279 | return usages; 280 | } 281 | } 282 | 283 | } 284 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/model/StackResolutionOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.model; 18 | 19 | import io.vertx.stack.resolver.ResolverOptions; 20 | 21 | import java.io.File; 22 | import java.util.List; 23 | 24 | /** 25 | * The options configuring the stack resolution. 26 | * 27 | * @author Clement Escoffier 28 | */ 29 | public class StackResolutionOptions extends ResolverOptions { 30 | 31 | private boolean failOnConflicts; 32 | 33 | private boolean cacheDisabled; 34 | 35 | private boolean cacheDisabledForSnapshots; 36 | 37 | private File cacheFile; 38 | 39 | /** 40 | * @return whether or not the resolution fails on conflicts or just prints a warning. 41 | */ 42 | public boolean isFailOnConflicts() { 43 | return failOnConflicts; 44 | } 45 | 46 | /** 47 | * Sets whether or not the resolution should fail on conflicts. 48 | * 49 | * @param failOnConflicts whether or not the resolution fails on conflicts. 50 | * @return the current {@link StackResolutionOptions} instance 51 | */ 52 | public StackResolutionOptions setFailOnConflicts(boolean failOnConflicts) { 53 | this.failOnConflicts = failOnConflicts; 54 | return this; 55 | } 56 | 57 | @Override 58 | public StackResolutionOptions setHttpProxy(String httpProxy) { 59 | super.setHttpProxy(httpProxy); 60 | return this; 61 | } 62 | 63 | @Override 64 | public StackResolutionOptions setHttpsProxy(String httpsProxy) { 65 | super.setHttpsProxy(httpsProxy); 66 | return this; 67 | } 68 | 69 | @Override 70 | public StackResolutionOptions setLocalRepository(String localRepository) { 71 | super.setLocalRepository(localRepository); 72 | return this; 73 | } 74 | 75 | @Override 76 | public StackResolutionOptions setRemoteRepositories(List remoteRepositories) { 77 | super.setRemoteRepositories(remoteRepositories); 78 | return this; 79 | } 80 | 81 | /** 82 | * @return whether or not the cache is disabled. 83 | */ 84 | public boolean isCacheDisabled() { 85 | return cacheDisabled; 86 | } 87 | 88 | /** 89 | * Sets whether or not the cache is disabled. 90 | * 91 | * @param cacheDisabled {@code true} to disable the cache, {@code false} to enable it (default) 92 | * @return the current {@link StackResolutionOptions} instance 93 | */ 94 | public StackResolutionOptions setCacheDisabled(boolean cacheDisabled) { 95 | this.cacheDisabled = cacheDisabled; 96 | return this; 97 | } 98 | 99 | /** 100 | * @return whether or not the cache is disabled for snapshots 101 | */ 102 | public boolean isCacheDisabledForSnapshots() { 103 | return cacheDisabledForSnapshots; 104 | } 105 | 106 | /** 107 | * Sets whether or not the cache is disabled for snapshot. 108 | * 109 | * @param cacheDisabledForSnapshots {@code true} to disable the cache for snapshot, {@code false} to enable it 110 | * (default) 111 | * @return the current {@link StackResolutionOptions} instance 112 | */ 113 | public StackResolutionOptions setCacheDisabledForSnapshots(boolean cacheDisabledForSnapshots) { 114 | this.cacheDisabledForSnapshots = cacheDisabledForSnapshots; 115 | return this; 116 | } 117 | 118 | /** 119 | * @return the location of the cache file is set. 120 | */ 121 | public File getCacheFile() { 122 | return cacheFile; 123 | } 124 | 125 | /** 126 | * Sets the cache file location (json file). 127 | * 128 | * @param cacheFile the cache file 129 | * @return the current {@link StackResolutionOptions} instance 130 | */ 131 | public StackResolutionOptions setCacheFile(File cacheFile) { 132 | this.cacheFile = cacheFile; 133 | return this; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/resolver/ResolutionOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.resolver; 18 | 19 | import java.util.*; 20 | 21 | /** 22 | * Options configuring the resolution of a single dependency. 23 | * 24 | * @author Clement Escoffier 25 | */ 26 | public class ResolutionOptions { 27 | 28 | private boolean withTransitive = true; 29 | private List exclusions = new ArrayList<>(); 30 | 31 | /** 32 | * @return whether or not the resolution should also resolve the transitive dependencies. 33 | */ 34 | public boolean isWithTransitive() { 35 | return withTransitive; 36 | } 37 | 38 | /** 39 | * Sets whether or not the resolution of the dependency should include the transitive dependencies. 40 | * 41 | * @param withTransitive whether or not the resolution should also resolve the transitive dependencies, {@code 42 | * true} by default. 43 | * @return the current {@link ResolutionOptions} instance 44 | */ 45 | public ResolutionOptions setWithTransitive(boolean withTransitive) { 46 | this.withTransitive = withTransitive; 47 | return this; 48 | } 49 | 50 | /** 51 | * Adds an exclusion. The excluded dependencies and its children would not be resolved. The exclusion is given 52 | * under the following form: {@code groupId:artifactId}. 53 | * 54 | * @param exclusion the exclusion to add 55 | * @return the current {@link ResolutionOptions} instance 56 | */ 57 | public ResolutionOptions addExclusion(String exclusion) { 58 | exclusions.add(exclusion); 59 | return this; 60 | } 61 | 62 | /** 63 | * Removes an exclusion. 64 | * 65 | * @param exclusion the exlusion to remove 66 | * @return the current {@link ResolutionOptions} instance 67 | * @see #addExclusion(String) 68 | */ 69 | public ResolutionOptions removeExclusion(String exclusion) { 70 | exclusions.remove(exclusion); 71 | return this; 72 | } 73 | 74 | /** 75 | * @return the list of exclusions, empty if none. 76 | */ 77 | public List getExclusions() { 78 | return exclusions; 79 | } 80 | 81 | @Override 82 | public boolean equals(Object o) { 83 | if (this == o) return true; 84 | if (o == null || getClass() != o.getClass()) return false; 85 | 86 | ResolutionOptions that = (ResolutionOptions) o; 87 | 88 | if (isWithTransitive() != that.isWithTransitive()) return false; 89 | 90 | Set set1 = new HashSet<>(); 91 | set1.addAll(that.getExclusions()); 92 | Set set2 = new HashSet<>(); 93 | set2.addAll(getExclusions()); 94 | return set1.equals(set2); 95 | } 96 | 97 | @Override 98 | public int hashCode() { 99 | int result = (isWithTransitive() ? 1 : 0); 100 | result = 31 * result + getExclusions().hashCode(); 101 | return result; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/resolver/Resolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.resolver; 18 | 19 | 20 | import io.vertx.stack.model.Artifact; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Interface implemented by resolver. Resolvers are responsible for the resolution of the dependencies. 26 | * 27 | * @author Clement Escoffier 28 | */ 29 | public interface Resolver { 30 | 31 | /** 32 | * Resolves a dependency. 33 | * 34 | * @param dependency the dependency, using the GACV form. 35 | * @param options the resolution options 36 | * @return the list of resolved artifacts. The list contains a single element if the transitive dependencies are 37 | * not resolved. The first artifact of the list if the artifact for the given dependency. 38 | */ 39 | List resolve(String dependency, ResolutionOptions options); 40 | 41 | /** 42 | * Creates a {@link Resolver} using the default implementation and default options. 43 | * 44 | * @return the created {@link Resolver}. 45 | */ 46 | static Resolver create() { 47 | return new ResolverImpl(new ResolverOptions()); 48 | } 49 | 50 | /** 51 | * Creates a {@link Resolver} using the default implementation and the given options. 52 | * 53 | * @param options the resolver options 54 | * @return the created {@link Resolver}. 55 | */ 56 | static Resolver create(ResolverOptions options) { 57 | return new ResolverImpl(options); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/resolver/ResolverImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.resolver; 18 | 19 | 20 | import io.vertx.core.internal.logging.Logger; 21 | import io.vertx.core.internal.logging.LoggerFactory; 22 | import io.vertx.stack.model.Artifact; 23 | import org.apache.maven.repository.internal.MavenRepositorySystemUtils; 24 | import org.eclipse.aether.DefaultRepositorySystemSession; 25 | import org.eclipse.aether.RepositorySystem; 26 | import org.eclipse.aether.RepositorySystemSession; 27 | import org.eclipse.aether.collection.CollectRequest; 28 | import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; 29 | import org.eclipse.aether.graph.Dependency; 30 | import org.eclipse.aether.graph.DependencyFilter; 31 | import org.eclipse.aether.graph.DependencyNode; 32 | import org.eclipse.aether.graph.Exclusion; 33 | import org.eclipse.aether.impl.DefaultServiceLocator; 34 | import org.eclipse.aether.repository.*; 35 | import org.eclipse.aether.resolution.DependencyRequest; 36 | import org.eclipse.aether.resolution.DependencyResolutionException; 37 | import org.eclipse.aether.resolution.DependencyResult; 38 | import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; 39 | import org.eclipse.aether.spi.connector.transport.TransporterFactory; 40 | import org.eclipse.aether.transport.file.FileTransporterFactory; 41 | import org.eclipse.aether.transport.http.HttpTransporterFactory; 42 | import org.eclipse.aether.util.artifact.JavaScopes; 43 | import org.eclipse.aether.util.filter.DependencyFilterUtils; 44 | import org.eclipse.aether.util.repository.AuthenticationBuilder; 45 | 46 | import java.net.MalformedURLException; 47 | import java.net.URL; 48 | import java.util.ArrayList; 49 | import java.util.Collection; 50 | import java.util.List; 51 | import java.util.stream.Collectors; 52 | import java.util.stream.Stream; 53 | 54 | /** 55 | * An implementation of {@link Resolver} based on Aether. 56 | * 57 | * @author Clement Escoffier 58 | */ 59 | public class ResolverImpl implements Resolver { 60 | 61 | private final static Logger LOGGER = LoggerFactory.getLogger("vertx-stack-resolver"); 62 | 63 | public static final String REMOTE_SNAPSHOT_POLICY_SYS_PROP = "vertx.maven.remoteSnapshotPolicy"; 64 | 65 | private final RepositorySystem system; 66 | private final LocalRepository localRepo; 67 | private final List remotes = new ArrayList<>(); 68 | 69 | /** 70 | * Creates a new instance of {@link ResolverImpl} with the given options. 71 | * 72 | * @param options the options 73 | */ 74 | public ResolverImpl(ResolverOptions options) { 75 | String localMavenRepo = options.getLocalRepository(); 76 | List remoteMavenRepos = options.getRemoteRepositories(); 77 | String httpProxy = options.getHttpProxy(); 78 | String httpsProxy = options.getHttpsProxy(); 79 | 80 | DefaultServiceLocator locator = getDefaultServiceLocator(); 81 | 82 | system = locator.getService(RepositorySystem.class); 83 | localRepo = new LocalRepository(localMavenRepo); 84 | Proxy proxy = getHttpProxy(httpProxy); 85 | Proxy secureProxy = getHttpsProxy(httpsProxy); 86 | 87 | configureRemoteRepositories(remoteMavenRepos, proxy, secureProxy); 88 | } 89 | 90 | private Proxy getHttpsProxy(String httpsProxy) { 91 | Proxy secureProxy = null; 92 | if (httpsProxy != null) { 93 | URL url = url(httpsProxy); 94 | Authentication authentication = extractAuth(url); 95 | secureProxy = new Proxy("https", url.getHost(), url.getPort(), authentication); 96 | } 97 | return secureProxy; 98 | } 99 | 100 | private Proxy getHttpProxy(String httpProxy) { 101 | Proxy proxy = null; 102 | if (httpProxy != null) { 103 | URL url = url(httpProxy); 104 | Authentication authentication = extractAuth(url); 105 | proxy = new Proxy("http", url.getHost(), url.getPort(), authentication); 106 | } 107 | return proxy; 108 | } 109 | 110 | private void configureRemoteRepositories(List remoteMavenRepos, Proxy proxy, Proxy secureProxy) { 111 | int count = 0; 112 | for (String remote : remoteMavenRepos) { 113 | URL url = url(remote); 114 | Authentication auth = extractAuth(url); 115 | if (auth != null) { 116 | url = url(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()); 117 | } 118 | RemoteRepository.Builder builder = new RemoteRepository.Builder("repo" + (count++), "default", url.toString()); 119 | if (auth != null) { 120 | builder.setAuthentication(auth); 121 | } 122 | switch (url.getProtocol()) { 123 | case "http": 124 | if (proxy != null) { 125 | builder.setProxy(proxy); 126 | } 127 | break; 128 | case "https": 129 | if (secureProxy != null) { 130 | builder.setProxy(secureProxy); 131 | } 132 | break; 133 | } 134 | customizeRemoteRepoBuilder(builder); 135 | RemoteRepository remoteRepo = builder.build(); 136 | remotes.add(remoteRepo); 137 | } 138 | } 139 | 140 | private static DefaultServiceLocator getDefaultServiceLocator() { 141 | DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); 142 | locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); 143 | locator.addService(TransporterFactory.class, FileTransporterFactory.class); 144 | locator.addService(TransporterFactory.class, HttpTransporterFactory.class); 145 | locator.setErrorHandler(new DefaultServiceLocator.ErrorHandler() { 146 | @Override 147 | public void serviceCreationFailed(Class type, Class impl, Throwable exception) { 148 | LOGGER.error("Service creation failure: " + exception.getMessage(), exception); 149 | } 150 | }); 151 | return locator; 152 | } 153 | 154 | private URL url(String u) { 155 | try { 156 | return new URL(u); 157 | } catch (MalformedURLException e) { 158 | LOGGER.error("Cannot create url from " + u, e); 159 | throw new IllegalArgumentException("Invalid url " + u); 160 | } 161 | } 162 | 163 | private URL url(String protocol, String host, int port, String file) { 164 | try { 165 | return new URL(protocol, host, port, file); 166 | } catch (MalformedURLException e) { 167 | final String url = "{protocol:" + protocol + ", host:" + host + ", port:" + port + ", file:" + file + "}"; 168 | LOGGER.error("Cannot create url from " + url, e); 169 | throw new IllegalArgumentException("Invalid url " + url); 170 | } 171 | } 172 | 173 | /** 174 | * Resolve the given artifact. 175 | * 176 | * @param artifact the artifact 177 | * @param withTransitive whether the transitive dependencies needs to be resolved too 178 | * @param exclusions the list of exclusions 179 | * @return the list of resolved artifacts 180 | */ 181 | private DependencyNode resolve(Artifact artifact, boolean withTransitive, List exclusions) { 182 | CollectRequest collectRequest = collectRequest(artifact, exclusions, remotes); 183 | DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, dependencyFilter()); 184 | RepositorySystemSession session = session(system, localRepo); 185 | try { 186 | DependencyResult dependencyResult = system.resolveDependencies(session, dependencyRequest); 187 | DependencyNode root = dependencyResult.getRoot(); 188 | if (withTransitive) { 189 | return root; 190 | } else { 191 | root.setChildren(new ArrayList<>()); 192 | return root; 193 | } 194 | } catch (DependencyResolutionException e) { 195 | throw new IllegalArgumentException("Cannot resolve artifact " + artifact.toString() + 196 | " in maven repositories: " + e.getMessage()); 197 | } 198 | } 199 | 200 | protected void customizeRemoteRepoBuilder(RemoteRepository.Builder builder) { 201 | String updatePolicy = System.getProperty(REMOTE_SNAPSHOT_POLICY_SYS_PROP); 202 | if (updatePolicy != null && !updatePolicy.isEmpty()) { 203 | builder.setSnapshotPolicy(new RepositoryPolicy(true, updatePolicy, RepositoryPolicy.CHECKSUM_POLICY_WARN)); 204 | } 205 | } 206 | 207 | private static Authentication extractAuth(URL url) { 208 | String userInfo = url.getUserInfo(); 209 | if (userInfo != null) { 210 | AuthenticationBuilder authBuilder = new AuthenticationBuilder(); 211 | int sep = userInfo.indexOf(':'); 212 | if (sep != -1) { 213 | authBuilder.addUsername(userInfo.substring(0, sep)); 214 | authBuilder.addPassword(userInfo.substring(sep + 1)); 215 | } else { 216 | authBuilder.addUsername(userInfo); 217 | } 218 | return authBuilder.build(); 219 | } 220 | return null; 221 | } 222 | 223 | private static RepositorySystemSession session(RepositorySystem system, LocalRepository localRepo) { 224 | DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); 225 | session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo)); 226 | return session; 227 | } 228 | 229 | private static CollectRequest collectRequest(Artifact artifact, List exclusions, List remotes) { 230 | CollectRequest collectRequest = new CollectRequest(); 231 | Dependency root = new Dependency(artifact, JavaScopes.COMPILE) 232 | .setExclusions( 233 | exclusions.stream() 234 | .map(e -> { 235 | // Exclusion are structured as groupId:artifactId. 236 | String[] segments = e.split(":"); 237 | if (segments.length != 2) { 238 | throw new IllegalStateException("Invalid exclusion format: " + e + " - exclusion are " + 239 | "structured as follows: groupId:artifactId"); 240 | } 241 | return new Exclusion(segments[0], segments[1], null, null); 242 | }) 243 | .collect(Collectors.toList())); 244 | collectRequest.setRoot(root); 245 | collectRequest.setRepositories(remotes); 246 | return collectRequest; 247 | } 248 | 249 | private static DependencyFilter dependencyFilter() { 250 | return 251 | DependencyFilterUtils.andFilter( 252 | DependencyFilterUtils.classpathFilter( 253 | JavaScopes.COMPILE 254 | ), 255 | // Remove optionals and dependencies of optionals 256 | (dependencyNode, list) -> { 257 | for (DependencyNode parent : list) { 258 | if (parent.getDependency().isOptional()) { 259 | return false; 260 | } 261 | } 262 | 263 | return !dependencyNode.getDependency().isOptional(); 264 | }, 265 | 266 | // Remove excluded dependencies 267 | (dependencyNode, list) -> { 268 | // Build the list of exclusion, traverse the tree. 269 | Collection ex = new ArrayList<>(); 270 | for (DependencyNode parent : list) { 271 | ex.addAll(parent.getDependency().getExclusions()); 272 | } 273 | 274 | for (Exclusion e : ex) { 275 | // Check the the passed artifact is excluded 276 | if (e.getArtifactId().equals(dependencyNode.getArtifact().getArtifactId()) 277 | && e.getGroupId().equals(dependencyNode.getArtifact().getGroupId())) { 278 | return false; 279 | } 280 | 281 | // Check if a parent artifact is excluded 282 | for (DependencyNode parent : list) { 283 | if (e.getArtifactId().equals(parent.getArtifact().getArtifactId()) 284 | && e.getGroupId().equals(parent.getArtifact().getGroupId())) { 285 | return false; 286 | } 287 | } 288 | } 289 | return true; 290 | }, 291 | 292 | // Remove provided dependencies and transitive dependencies of provided dependencies 293 | (dependencyNode, list) -> { 294 | for (DependencyNode parent : list) { 295 | if (!parent.getDependency().getScope().equalsIgnoreCase("compile")) { 296 | return false; 297 | } 298 | } 299 | return dependencyNode.getDependency().getScope().equalsIgnoreCase("compile"); 300 | } 301 | ); 302 | } 303 | 304 | @Override 305 | public List resolve(String gacv, ResolutionOptions options) { 306 | DependencyNode root = resolve(new Artifact(gacv), options.isWithTransitive(), options.getExclusions()); 307 | List exclusions = Stream.concat(Stream.of(root), root.getChildren().stream()) 308 | .map(DependencyNode::getDependency) 309 | .flatMap(dependency -> dependency.getExclusions().stream()) 310 | .collect(Collectors.toList()); 311 | Artifact rootArtifact = new Artifact(root.getArtifact(), null); 312 | return Stream 313 | .concat(Stream.of(rootArtifact), toArtifacts(root, rootArtifact, exclusions)) 314 | .collect(Collectors.toList()); 315 | } 316 | 317 | private Stream toArtifacts(DependencyNode dependencyNode, Artifact rootArtifact, List exclusions) { 318 | return dependencyNode.getChildren().stream() 319 | // remove optional dependencies 320 | .filter(childNode -> !childNode.getDependency().isOptional()) 321 | // remove excluded dependencies 322 | .filter(childNode -> exclusions.stream().noneMatch(exclusion -> 323 | exclusion.getGroupId().equals(childNode.getArtifact().getGroupId()) 324 | && exclusion.getArtifactId().equals(childNode.getArtifact().getArtifactId()))) 325 | // remove provided dependencies and transitive dependencies of provided dependencies 326 | .filter(childNode -> childNode.getDependency().getScope().equalsIgnoreCase("compile")) 327 | .flatMap(childNode -> { 328 | Artifact childArtifact = new Artifact(childNode.getArtifact(), rootArtifact); 329 | return Stream.concat(Stream.of(childArtifact), toArtifacts(childNode, childArtifact, exclusions)); 330 | }); 331 | } 332 | 333 | } 334 | 335 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/resolver/ResolverOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.resolver; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | /** 24 | * Options to configure the resolver. 25 | * 26 | * @author Clement Escoffier 27 | */ 28 | public class ResolverOptions { 29 | 30 | public static final String LOCAL_REPO_SYS_PROP = "vertx.maven.localRepo"; 31 | public static final String REMOTE_REPOS_SYS_PROP = "vertx.maven.remoteRepos"; 32 | public static final String HTTP_PROXY_SYS_PROP = "vertx.maven.httpProxy"; 33 | public static final String HTTPS_PROXY_SYS_PROP = "vertx.maven.httpsProxy"; 34 | 35 | private static final String USER_HOME = System.getProperty("user.home"); 36 | private static final String FILE_SEP = System.getProperty("file.separator"); 37 | private static final String DEFAULT_MAVEN_LOCAL = USER_HOME + FILE_SEP + ".m2" + FILE_SEP + "repository"; 38 | private static final String SNAPSHOT_REPO = System.getProperty("vertx.snapshotRepository"); 39 | private static final String DEFAULT_MAVEN_REMOTES = 40 | "https://repo1.maven.org/maven2/ " + SNAPSHOT_REPO; 41 | 42 | private String localRepository = System.getProperty(LOCAL_REPO_SYS_PROP, DEFAULT_MAVEN_LOCAL); 43 | 44 | private List remoteRepositories = 45 | new ArrayList<>(Arrays.asList(System.getProperty(REMOTE_REPOS_SYS_PROP, DEFAULT_MAVEN_REMOTES).split(" "))); 46 | 47 | private String httpProxy = System.getProperty(HTTP_PROXY_SYS_PROP); 48 | private String httpsProxy = System.getProperty(HTTPS_PROXY_SYS_PROP); 49 | 50 | /** 51 | * @return the configured proxy address for HTTP request, {@code null} if none. 52 | */ 53 | public String getHttpProxy() { 54 | return httpProxy; 55 | } 56 | 57 | /** 58 | * Sets the address of the proxy used for HTTP requests. 59 | * 60 | * @param httpProxy the proxy address 61 | * @return the current {@link ResolverOptions} instance 62 | */ 63 | public ResolverOptions setHttpProxy(String httpProxy) { 64 | this.httpProxy = httpProxy; 65 | return this; 66 | } 67 | 68 | /** 69 | * @return the configured proxy address for HTTPS request, {@code null} if none. 70 | */ 71 | public String getHttpsProxy() { 72 | return httpsProxy; 73 | } 74 | 75 | /** 76 | * Sets the address of the proxy used for HTTPS requests. 77 | * 78 | * @param httpsProxy the proxy address 79 | * @return the current {@link ResolverOptions} instance 80 | */ 81 | public ResolverOptions setHttpsProxy(String httpsProxy) { 82 | this.httpsProxy = httpsProxy; 83 | return this; 84 | } 85 | 86 | /** 87 | * @return the path of the local repository. By default it's ~/.m2/repository. 88 | */ 89 | public String getLocalRepository() { 90 | return localRepository; 91 | } 92 | 93 | /** 94 | * Sets the path to the local Maven repository. By default it's ~/.m2/repository. 95 | * 96 | * @param localRepository the local repository 97 | * @return the current {@link ResolverOptions} instance 98 | */ 99 | public ResolverOptions setLocalRepository(String localRepository) { 100 | this.localRepository = localRepository; 101 | return this; 102 | } 103 | 104 | /** 105 | * @return the list of remove repositories. 106 | */ 107 | public List getRemoteRepositories() { 108 | if (remoteRepositories == null || remoteRepositories.isEmpty()) { 109 | String remoteString = System.getProperty(REMOTE_REPOS_SYS_PROP, DEFAULT_MAVEN_REMOTES); 110 | // They are space-delimited (space is illegal char in urls) 111 | remoteRepositories = Arrays.asList(remoteString.split(" ")); 112 | } 113 | return remoteRepositories; 114 | } 115 | 116 | /** 117 | * Sets the list of remote repositories used by the resolver. The repository must use the Maven 2 repository 118 | * layout. If you don't want to resolved from remote locations, set it to an empty list. By default it resolves 119 | * from Maven central and Sonatype OSS Snapshots. 120 | * 121 | * @param remoteRepositories the list of remote repositories 122 | * @return the current {@link ResolverOptions} instance 123 | */ 124 | public ResolverOptions setRemoteRepositories(List remoteRepositories) { 125 | this.remoteRepositories = remoteRepositories; 126 | return this; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/utils/Actions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import io.vertx.core.internal.logging.LoggerFactory; 20 | import org.eclipse.aether.artifact.Artifact; 21 | 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.nio.file.Files; 25 | import java.nio.file.Path; 26 | 27 | /** 28 | * Common {@link Action} implementation. 29 | * 30 | * @author Clement Escoffier 31 | */ 32 | public class Actions { 33 | 34 | /** 35 | * Wraps an action that is applied when the resolution is completed. 36 | */ 37 | public interface Action { 38 | 39 | /** 40 | * Executes the action. 41 | * Actions may throw a runtime exception if something bad happened when the action is executed. 42 | */ 43 | void execute(); 44 | } 45 | 46 | private final static io.vertx.core.internal.logging.Logger LOGGER = LoggerFactory.getLogger("Stack Resolver"); 47 | 48 | /** 49 | * Action to copy an artifact to a directory. 50 | * 51 | * @param artifact the artifact 52 | * @param directory the directory 53 | * @return the created {@link Action} 54 | */ 55 | public static Action copy(Artifact artifact, File directory) { 56 | return () -> { 57 | Path source = artifact.getFile().toPath(); 58 | Path output = directory.toPath().resolve(source.getFileName()); 59 | LOGGER.info("Copying " + source.getFileName()); 60 | try { 61 | Files.copy(source, output); 62 | } catch (IOException e) { 63 | throw new RuntimeException(e); 64 | } 65 | }; 66 | } 67 | 68 | /** 69 | * Action denoting that nothing needs to be done for the given artifact. 70 | * 71 | * @param artifact the artifact 72 | * @return the created {@link Action} 73 | */ 74 | public static Action skip(Artifact artifact) { 75 | return () -> LOGGER.info("Skipping " + artifact.toString()); 76 | } 77 | 78 | /** 79 | * Action removing a file. 80 | * 81 | * @param file the file to be removed 82 | * @return the created {@link Action} 83 | */ 84 | public static Action remove(File file) { 85 | return () -> { 86 | if (file.isFile()) { 87 | LOGGER.info("Deleting " + file.getName()); 88 | file.delete(); 89 | } 90 | }; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/utils/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonParser; 20 | import com.fasterxml.jackson.databind.*; 21 | import com.fasterxml.jackson.databind.module.SimpleModule; 22 | import io.vertx.core.internal.logging.Logger; 23 | import io.vertx.core.internal.logging.LoggerFactory; 24 | import io.vertx.stack.model.Artifact; 25 | import io.vertx.stack.resolver.ResolutionOptions; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.Optional; 32 | 33 | /** 34 | * A cache storing the resolution result. 35 | * 36 | * @author Clement Escoffier 37 | */ 38 | public class Cache { 39 | private final static Logger LOGGER = LoggerFactory.getLogger("stack-manager-cache"); 40 | 41 | // We don't use the MAPPEr from vert.x because it requires some tuning. 42 | private static final ObjectMapper MAPPER = new ObjectMapper().registerModule( 43 | new SimpleModule("artifact-module").addDeserializer(Artifact.class, new JsonDeserializer() { 44 | @Override 45 | public Artifact deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 46 | JsonNode node = p.getCodec().readTree(p); 47 | return fromJsonNode(node); 48 | } 49 | 50 | private Artifact fromJsonNode(JsonNode node) { 51 | JsonNode viaNode = node.get("via"); 52 | Artifact via; 53 | if (viaNode == null || viaNode.asText().equalsIgnoreCase("null")) { 54 | via = null; 55 | } else { 56 | via = fromJsonNode(viaNode); 57 | } 58 | 59 | Artifact artifact; 60 | if (!node.get("classifier").asText().isEmpty()) { 61 | artifact = new Artifact(node.get("groupId").asText(), node.get("artifactId").asText(), 62 | node.get("classifier").asText(), node.get("extension").asText(), node.get("version").asText(), via); 63 | } else { 64 | artifact = new Artifact(node.get("groupId").asText(), node.get("artifactId").asText(), 65 | node.get("extension").asText(), node.get("version").asText(), via); 66 | } 67 | return artifact.setFile(new File(node.get("file").asText())); 68 | } 69 | })); 70 | 71 | private final boolean disabled; 72 | private final boolean disabledForSnapshot; 73 | 74 | List cache = new ArrayList<>(); 75 | private File cacheFile; 76 | 77 | 78 | public Cache(boolean disabled, boolean disabledForSnapshot, File cacheFile) { 79 | this.disabled = disabled; 80 | this.disabledForSnapshot = disabledForSnapshot; 81 | this.cacheFile = cacheFile; 82 | 83 | // Load cache. 84 | if (this.cacheFile == null && Home.getVertxHome() != null) { 85 | this.cacheFile = new File(Home.getVertxHome(), ".stack-manager-cache.json"); 86 | LOGGER.info("Set resolver cache to " + this.cacheFile.getAbsolutePath()); 87 | } 88 | 89 | if (this.cacheFile != null && !this.cacheFile.isFile()) { 90 | this.cacheFile.getParentFile().mkdirs(); 91 | } 92 | 93 | if (!disabled && this.cacheFile != null && this.cacheFile.isFile()) { 94 | LOGGER.info("Loading resolver cache from " + this.cacheFile.getAbsolutePath()); 95 | JavaType type = MAPPER.getTypeFactory(). 96 | constructCollectionType(List.class, CacheEntry.class); 97 | try { 98 | cache.addAll(MAPPER.readValue(this.cacheFile, type)); 99 | } catch (IOException e) { 100 | LOGGER.error("Cannot read the cache entries from " + this.cacheFile.getAbsolutePath() + ": " + e.getMessage()); 101 | } 102 | } 103 | } 104 | 105 | public void writeCacheOnFile() { 106 | if (disabled) { 107 | return; 108 | } 109 | if (cacheFile != null) { 110 | try { 111 | MAPPER.writer().writeValue(cacheFile, cache); 112 | } catch (IOException e) { 113 | LOGGER.error("Cannot write the cache entries to " + cacheFile.getAbsolutePath() + ": " + e.getMessage()); 114 | } 115 | } 116 | } 117 | 118 | public List get(String gacv, ResolutionOptions resolutionOptions) { 119 | if (disabled) { 120 | return null; 121 | } 122 | 123 | if (disabledForSnapshot && gacv.contains("SNAPSHOT")) { 124 | return null; 125 | } 126 | 127 | Optional entry = find(gacv, resolutionOptions); 128 | if (entry.isPresent()) { 129 | if (isValid(entry.get())) { 130 | return entry.get().getArtifacts(); 131 | } else { 132 | // cleanup required 133 | cache.remove(entry.get()); 134 | return null; 135 | } 136 | } 137 | return null; 138 | } 139 | 140 | private boolean isValid(CacheEntry entry) { 141 | // If valid check two aspects: 142 | // All artifact files must be existing and non empty 143 | // If the dependency is a snapshot, it must check the insertion date. 144 | if (entry.getArtifacts().isEmpty()) { 145 | return false; 146 | } 147 | 148 | if (entry.getArtifacts().stream().anyMatch(artifact -> !artifact.getFile().isFile())) { 149 | return false; 150 | } 151 | 152 | if (entry.gacv.contains("SNAPSHOT")) { 153 | long now = System.currentTimeMillis(); 154 | long insertion = entry.getInsertionTime(); 155 | return now - insertion < 24 * 60 * 60 * 1000; // 24 hours of 60 minutes composed by 60 seconds. 156 | } 157 | return true; 158 | } 159 | 160 | 161 | public void put(String gacv, ResolutionOptions resolutionOptions, List list) { 162 | if (disabled) { 163 | return; 164 | } 165 | 166 | if (disabledForSnapshot && gacv.contains("SNAPSHOT")) { 167 | return; 168 | } 169 | 170 | Optional entry = find(gacv, resolutionOptions); 171 | if (entry.isPresent()) { 172 | CacheEntry cached = entry.get(); 173 | cached.setInsertionTime(System.currentTimeMillis()).setArtifacts(list); 174 | } else { 175 | CacheEntry cached = new CacheEntry(); 176 | cached.setArtifacts(list) 177 | .setGacv(gacv) 178 | .setOptions(resolutionOptions) 179 | .setInsertionTime(System.currentTimeMillis()); 180 | cache.add(cached); 181 | } 182 | } 183 | 184 | public Optional find(String gacv, ResolutionOptions options) { 185 | return cache.stream().filter(entry -> entry.gacv.equals(gacv) 186 | && entry.options.equals(options)).findFirst(); 187 | } 188 | 189 | public int size() { 190 | return cache.size(); 191 | } 192 | 193 | public static class CacheEntry { 194 | String gacv; 195 | ResolutionOptions options; 196 | List artifacts = new ArrayList<>(); 197 | 198 | long insertionTime; 199 | 200 | public CacheEntry() { 201 | } 202 | 203 | public List getArtifacts() { 204 | return artifacts; 205 | } 206 | 207 | public CacheEntry setArtifacts(List artifacts) { 208 | this.artifacts = artifacts; 209 | return this; 210 | } 211 | 212 | public String getGacv() { 213 | return gacv; 214 | } 215 | 216 | public CacheEntry setGacv(String gacv) { 217 | this.gacv = gacv; 218 | return this; 219 | } 220 | 221 | public long getInsertionTime() { 222 | return insertionTime; 223 | } 224 | 225 | public CacheEntry setInsertionTime(long insertionTime) { 226 | this.insertionTime = insertionTime; 227 | return this; 228 | } 229 | 230 | public ResolutionOptions getOptions() { 231 | return options; 232 | } 233 | 234 | public CacheEntry setOptions(ResolutionOptions options) { 235 | this.options = options; 236 | return this; 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/utils/Filtering.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Utility class to handle Maven-like filtering. 23 | * 24 | * @author Clement Escoffier 25 | */ 26 | public class Filtering { 27 | 28 | private Filtering() { 29 | // Avoid direct instantiation 30 | } 31 | 32 | /** 33 | * Filters the given input using the given set of variables. 34 | * 35 | * @param input the input 36 | * @param variables the variables 37 | * @return the modified input 38 | */ 39 | public static String filter(String input, Map variables) { 40 | if (variables.isEmpty()) { 41 | return input; 42 | } 43 | 44 | if (input == null || input.isEmpty()) { 45 | return input; 46 | } 47 | 48 | String current = input; 49 | String last = input; 50 | while (current.contains("${") && current.contains("}")) { 51 | 52 | // Replace all variables 53 | for (Map.Entry entry : variables.entrySet()) { 54 | current = current.replace("${" + entry.getKey() + "}", entry.getValue()); 55 | } 56 | 57 | // If we didn't change anything, just leave. 58 | if (last.equals(current)) { 59 | return current; 60 | } 61 | 62 | last = current; 63 | } 64 | 65 | return current; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /stack-manager/src/main/java/io/vertx/stack/utils/Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.io.File; 20 | 21 | /** 22 | * Helper method to find vert.x home. 23 | * 24 | * @author Clement Escoffier 25 | */ 26 | public class Home { 27 | 28 | /** 29 | * Try to find the home of vert.x using the `VERTX_HOME` env variable or the `vertx.home` system property. 30 | * 31 | * @return the found directory, {@code null} if not set. 32 | */ 33 | public static File getVertxHome() { 34 | // System property ? 35 | String home = System.getProperty("vertx.home"); 36 | if (home != null) { 37 | return new File(home); 38 | } 39 | // Environment variable 40 | home = System.getenv("VERTX_HOME"); 41 | if (home != null) { 42 | return new File(home); 43 | } 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /stack-manager/src/main/resources/META-INF/services/io.vertx.core.spi.launcher.CommandFactory: -------------------------------------------------------------------------------- 1 | io.vertx.stack.command.ResolveCommandFactory -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/DescriptorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack; 18 | 19 | import com.jayway.awaitility.Awaitility; 20 | import io.vertx.core.Launcher; 21 | import io.vertx.core.impl.launcher.VertxCommandLauncher; 22 | import io.vertx.core.spi.launcher.ExecutionContext; 23 | import io.vertx.stack.command.ResolveCommand; 24 | import io.vertx.stack.utils.FileUtils; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | 28 | import java.io.File; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.concurrent.TimeUnit; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | /** 36 | * @author Clement Escoffier 37 | */ 38 | public class DescriptorTest { 39 | 40 | private File root = new File("target/stack"); 41 | 42 | @Before 43 | public void setUp() { 44 | FileUtils.delete(root); 45 | Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !root.exists()); 46 | } 47 | 48 | @Test 49 | public void testResolutionOfCore() { 50 | ResolveCommand cmd = new ResolveCommand(); 51 | cmd.setFailOnConflict(false); 52 | cmd.setDirectory(root.getAbsolutePath()); 53 | cmd.setStackDescriptor(new File("src/test/resources/stacks/core.json").getAbsolutePath()); 54 | cmd.setUp(new ExecutionContext(cmd, new VertxCommandLauncher(), null)); 55 | cmd.run(); 56 | assertThat(new File(root, "vertx-core-3.1.0.jar")).isFile(); 57 | } 58 | 59 | @Test 60 | public void testResolutionOfCoreWithVariable() { 61 | ResolveCommand cmd = new ResolveCommand(); 62 | cmd.setFailOnConflict(false); 63 | cmd.setDirectory(root.getAbsolutePath()); 64 | cmd.setStackDescriptor(new File("src/test/resources/stacks/core-with-variable.json").getAbsolutePath()); 65 | cmd.setUp(new ExecutionContext(cmd, new VertxCommandLauncher(), null)); 66 | cmd.run(); 67 | assertThat(new File(root, "vertx-core-3.1.0.jar")).isFile(); 68 | } 69 | 70 | @Test 71 | public void testResolutionOfCoreUsingSystemVariable() { 72 | List args = new ArrayList<>(); 73 | args.add("resolve"); 74 | args.add("--dir=" + root.getAbsolutePath()); 75 | args.add("-Dvertx.version=3.1.0"); 76 | args.add(new File("src/test/resources/stacks/core-with-system-variable.json").getAbsolutePath()); 77 | Launcher.main(args.toArray(new String[args.size()])); 78 | 79 | assertThat(new File(root, "vertx-core-3.1.0.jar")).isFile(); 80 | } 81 | 82 | @Test 83 | public void testResolutionWithDefaultDescriptor() { 84 | File defaultStack = new File("vertx-stack.json"); 85 | FileUtils.copyFile(new File("src/test/resources/stacks/core-with-system-variable.json"), 86 | defaultStack); 87 | 88 | List args = new ArrayList<>(); 89 | args.add("resolve"); 90 | args.add("--dir=" + root.getAbsolutePath()); 91 | args.add("-Dvertx.version=3.1.0"); 92 | Launcher.main(args.toArray(new String[args.size()])); 93 | 94 | assertThat(new File(root, "vertx-core-3.1.0.jar")).isFile(); 95 | defaultStack.delete(); 96 | } 97 | 98 | @Test 99 | public void testResolutionWithDefaultDescriptorInVertxHome() { 100 | File home = new File("target/home"); 101 | home.mkdirs(); 102 | System.setProperty("vertx.home", home.getAbsolutePath()); 103 | 104 | FileUtils.copyFile(new File("src/test/resources/stacks/core-with-system-variable.json"), 105 | new File(home, "vertx-stack.json")); 106 | 107 | List args = new ArrayList<>(); 108 | args.add("resolve"); 109 | args.add("-Dvertx.version=3.1.0"); 110 | Launcher.main(args.toArray(new String[args.size()])); 111 | 112 | assertThat(new File(home, "lib/vertx-core-3.1.0.jar")).isFile(); 113 | System.clearProperty("vertx.home"); 114 | } 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/StackResolutionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack; 18 | 19 | import com.jayway.awaitility.Awaitility; 20 | import io.vertx.stack.model.*; 21 | import io.vertx.stack.utils.FileUtils; 22 | import io.vertx.stack.utils.LocalArtifact; 23 | import io.vertx.stack.utils.LocalDependency; 24 | import io.vertx.stack.utils.LocalRepoBuilder; 25 | import org.apache.maven.model.Exclusion; 26 | import org.junit.After; 27 | import org.junit.Before; 28 | import org.junit.Test; 29 | 30 | import java.io.File; 31 | import java.util.Map; 32 | import java.util.concurrent.TimeUnit; 33 | 34 | import static org.assertj.core.api.Assertions.*; 35 | 36 | /** 37 | * @author Clement Escoffier 38 | */ 39 | public class StackResolutionTest { 40 | 41 | private final File root = new File("target/stack"); 42 | 43 | private final static StackResolutionOptions STRICT = new StackResolutionOptions().setFailOnConflicts(true); 44 | 45 | @Before 46 | public void setUp() { 47 | FileUtils.delete(root); 48 | Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !root.exists()); 49 | } 50 | 51 | @After 52 | public void tearDown() { 53 | System.clearProperty("vertx.version"); 54 | } 55 | 56 | @Test 57 | public void testTheResolutionOfAVerySmallStack() { 58 | Stack stack = new Stack().addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")); 59 | StackResolution resolution = new StackResolution(stack, root, STRICT); 60 | Map map = resolution.resolve(); 61 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 62 | } 63 | 64 | @Test 65 | public void testTheResolutionOfAVerySmallStackWithFiltering() { 66 | Stack stack = new Stack().addDependency(new Dependency("io.vertx", "vertx-core", "${vertx.version}")) 67 | .addVariable("vertx.version", "3.1.0"); 68 | StackResolution resolution = new StackResolution(stack, root, STRICT); 69 | Map map = resolution.resolve(); 70 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 71 | } 72 | 73 | @Test 74 | public void testTheResolutionOfVertxCoreWithoutTransitive() { 75 | Stack stack = new Stack().addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0").setTransitive(false)); 76 | StackResolution resolution = new StackResolution(stack, root, STRICT); 77 | Map map = resolution.resolve(); 78 | assertThat(map).containsKeys("io.vertx:vertx-core:jar:3.1.0").hasSize(1); 79 | } 80 | 81 | @Test 82 | public void testNoConflictWhenADependencyIsDeclaredTwice() { 83 | Dependency dependency = new Dependency("io.vertx", "vertx-core", "3.1.0"); 84 | Stack stack = new Stack() 85 | .addDependency(dependency) 86 | .addDependency(new Dependency("com.fasterxml.jackson.core", "jackson-databind", "2.6.1")); 87 | 88 | StackResolution resolution = new StackResolution(stack, root, STRICT); 89 | Map map = resolution.resolve(); 90 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 91 | assertThat(map).containsKey("com.fasterxml.jackson.core:jackson-databind:jar:2.6.1"); 92 | } 93 | 94 | @Test(expected = DependencyConflictException.class) 95 | public void testConflictOnDependencyVersionMismatch() { 96 | Dependency dependency = new Dependency("io.vertx", "vertx-core", "3.1.0"); 97 | Stack stack = new Stack() 98 | .addDependency(dependency) 99 | .addDependency(new Dependency("com.fasterxml.jackson.core", "jackson-databind", "2.4.1.3")); 100 | 101 | StackResolution resolution = new StackResolution(stack, root, STRICT); 102 | resolution.resolve(); 103 | } 104 | 105 | @Test 106 | public void testConflictManagementUsingExclusions() { 107 | Dependency dependency = new Dependency("io.vertx", "vertx-core", "3.1.0"); 108 | Exclusion exclusion1 = new Exclusion(); 109 | exclusion1.setGroupId("com.fasterxml.jackson.core"); 110 | exclusion1.setArtifactId("jackson-databind"); 111 | Exclusion exclusion2 = new Exclusion(); 112 | exclusion2.setGroupId("com.fasterxml.jackson.core"); 113 | exclusion2.setArtifactId("jackson-core"); 114 | dependency.addExclusion(exclusion1); 115 | dependency.addExclusion(exclusion2); 116 | Stack stack = new Stack() 117 | .addDependency(dependency) 118 | // Not the version used by vert.x 119 | .addDependency(new Dependency("com.fasterxml.jackson.core", "jackson-databind", "2.4.1.3")); 120 | StackResolution resolution = new StackResolution(stack, root, STRICT); 121 | resolution.resolve(); 122 | Map map = resolution.resolve(); 123 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 124 | assertThat(map).containsKey("com.fasterxml.jackson.core:jackson-databind:jar:2.4.1.3"); 125 | } 126 | 127 | @Test 128 | public void testModificationOfStack() { 129 | Stack stack = new Stack() 130 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 131 | .addDependency(new Dependency("io.vertx", "vertx-stomp", "3.1.0").setIncluded(false)); 132 | 133 | StackResolution resolution = new StackResolution(stack, root, STRICT); 134 | Map resolved = resolution.resolve(); 135 | assertThat(resolved).doesNotContainKeys("io.vertx:vertx-stomp:jar:3.1.0"); 136 | int numberOfArtifacts = root.listFiles().length; 137 | 138 | // include stomp 139 | stack = new Stack() 140 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 141 | .addDependency(new Dependency("io.vertx", "vertx-stomp", "3.1.0").setIncluded(true)); 142 | resolution = new StackResolution(stack, root, STRICT); 143 | resolved = resolution.resolve(); 144 | assertThat(resolved).containsKey("io.vertx:vertx-stomp:jar:3.1.0"); 145 | 146 | // remove stomp 147 | stack = new Stack() 148 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 149 | .addDependency(new Dependency("io.vertx", "vertx-stomp", "3.1.0").setIncluded(false)); 150 | 151 | resolution = new StackResolution(stack, root, STRICT); 152 | resolved = resolution.resolve(); 153 | assertThat(resolved).doesNotContainKeys("io.vertx:vertx-stomp:jar:3.1.0"); 154 | int numberOfArtifacts2 = root.listFiles().length; 155 | assertThat(numberOfArtifacts).isEqualTo(numberOfArtifacts2); 156 | } 157 | 158 | @Test(expected = IllegalArgumentException.class) 159 | public void testTheResolutionWhenAnArtifactIsMissing() { 160 | Stack stack = new Stack() 161 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 162 | .addDependency(new Dependency("io.vertx", "vertx-missing", "3.1.0")); 163 | StackResolution resolution = new StackResolution(stack, root, STRICT); 164 | resolution.resolve(); 165 | } 166 | 167 | @Test(expected = IllegalArgumentException.class) 168 | public void testTheResolutionWhenATransitiveDependencyIsMissing() { 169 | File local = new File("target/test-repos/incomplete"); 170 | new LocalRepoBuilder(local).addArtifact(new LocalArtifact("org.acme", "acme", "1.0").generateMainArtifact() 171 | .addDependency(new LocalDependency("org.acme", "acme-missing", "1.0"))).build(); 172 | Stack stack = new Stack() 173 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 174 | .addDependency(new Dependency("org.acme", "acme", "1.0", "txt")); 175 | StackResolutionOptions options = new StackResolutionOptions().setFailOnConflicts(true) 176 | .setLocalRepository(local.getAbsolutePath()) 177 | .setCacheDisabled(true); 178 | StackResolution resolution = new StackResolution(stack, root, options); 179 | resolution.resolve(); 180 | } 181 | 182 | @Test 183 | public void testTheResolutionWhenATransitiveDependencyIsMissingButExcluded() { 184 | File local = new File("target/test-repos/incomplete"); 185 | new LocalRepoBuilder(local).addArtifact(new LocalArtifact("org.acme", "acme", "1.0").generateMainArtifact() 186 | .addDependency(new LocalDependency("org.acme", "acme-missing", "1.0"))).build(); 187 | 188 | Exclusion exclusion = new Exclusion(); 189 | exclusion.setArtifactId("acme-missing"); 190 | exclusion.setGroupId("org.acme"); 191 | 192 | Dependency dependency = new Dependency("org.acme", "acme", "1.0", "txt"); 193 | dependency.addExclusion(exclusion); 194 | 195 | Stack stack = new Stack() 196 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 197 | .addDependency(dependency); 198 | StackResolutionOptions options = new StackResolutionOptions().setFailOnConflicts(true) 199 | .setLocalRepository(local.getAbsolutePath()); 200 | StackResolution resolution = new StackResolution(stack, root, options); 201 | Map map = resolution.resolve(); 202 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 203 | assertThat(map).containsKey("org.acme:acme:txt:1.0"); 204 | } 205 | 206 | @Test 207 | public void testTheResolutionWhenATransitiveDependencyIsMissingButOptional() { 208 | File local = new File("target/test-repos/incomplete"); 209 | new LocalRepoBuilder(local).addArtifact(new LocalArtifact("org.acme", "acme", "1.0").generateMainArtifact() 210 | .addDependency(new LocalDependency("org.acme", "acme-missing", "1.0").optional(true))).build(); 211 | 212 | Exclusion exclusion = new Exclusion(); 213 | exclusion.setArtifactId("acme-missing"); 214 | exclusion.setGroupId("org.acme"); 215 | 216 | Dependency dependency = new Dependency("org.acme", "acme", "1.0", "txt"); 217 | Stack stack = new Stack() 218 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 219 | .addDependency(dependency); 220 | StackResolutionOptions options = new StackResolutionOptions().setFailOnConflicts(true) 221 | .setLocalRepository(local.getAbsolutePath()); 222 | StackResolution resolution = new StackResolution(stack, root, options); 223 | Map map = resolution.resolve(); 224 | assertThat(map).containsKey("io.vertx:vertx-core:jar:3.1.0"); 225 | assertThat(map).containsKey("org.acme:acme:txt:1.0"); 226 | } 227 | 228 | @Test 229 | public void testModificationOfStackIntroducingConflict() { 230 | Stack stack = new Stack() 231 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 232 | .addDependency(new Dependency("io.vertx", "vertx-stomp", "3.1.0").setIncluded(false)) 233 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.0.0").setIncluded(false)); 234 | 235 | StackResolution resolution = new StackResolution(stack, root, STRICT); 236 | Map resolved = resolution.resolve(); 237 | assertThat(resolved).doesNotContainKeys("io.vertx:vertx-core:jar:3.0.0"); 238 | 239 | stack = new Stack() 240 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.1.0")) 241 | .addDependency(new Dependency("io.vertx", "vertx-stomp", "3.1.0").setIncluded(true)) 242 | .addDependency(new Dependency("io.vertx", "vertx-core", "3.0.0").setIncluded(true)); 243 | resolution = new StackResolution(stack, root, STRICT); 244 | try { 245 | resolved = resolution.resolve(); 246 | fail("Conflict expected"); 247 | } catch (DependencyConflictException e) { 248 | // OK 249 | } 250 | 251 | assertThat(resolved).containsKey("io.vertx:vertx-core:jar:3.1.0"); 252 | assertThat(resolved).doesNotContainKeys("io.vertx:vertx-core:jar:3.0.0"); 253 | assertThat(resolved).doesNotContainKeys("io.vertx:vertx-stomp:jar:3.1.0"); 254 | } 255 | 256 | @Test 257 | public void testTheResolutionWhenATransitiveDependencyConflicts() { 258 | // This stack introduces a dependency conflict: 259 | // vertx-web-templ-pug:4.4.8 depends transitively on a newer version of org.jetbrains:annotations 260 | // than vertx-lang-kotlin:4.4.8 261 | Stack stack = new Stack() 262 | .addDependency(new Dependency("io.vertx", "vertx-web-templ-pug", "4.4.8")) 263 | .addDependency(new Dependency("io.vertx", "vertx-lang-kotlin", "4.4.8")); 264 | 265 | StackResolution resolution = new StackResolution(stack, root, STRICT); 266 | 267 | assertThatThrownBy(resolution::resolve) 268 | .isInstanceOf(DependencyConflictException.class) 269 | .hasMessage("Conflict detected for artifact org.jetbrains:annotations:jar - " + 270 | "version 15.0 was already selected by [io.vertx:vertx-web-templ-pug:jar:4.4.8] " + 271 | "while io.vertx:vertx-lang-kotlin:jar:4.4.8 depends on version 13.0" + 272 | " - see the following chain:\n" + 273 | "io.vertx:vertx-lang-kotlin:jar:4.4.8\n" + 274 | "\t\\-- org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.7.21\n" + 275 | "\t\t\\-- org.jetbrains.kotlin:kotlin-stdlib:jar:1.7.21\n" + 276 | "\t\t\t\\-- org.jetbrains:annotations:jar:13.0"); 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/VertxStacksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack; 18 | 19 | import com.jayway.awaitility.Awaitility; 20 | import io.vertx.core.impl.launcher.commands.VersionCommand; 21 | import io.vertx.stack.model.Dependency; 22 | import io.vertx.stack.model.Stack; 23 | import io.vertx.stack.model.StackResolution; 24 | import io.vertx.stack.model.StackResolutionOptions; 25 | import io.vertx.stack.utils.FileUtils; 26 | import org.junit.After; 27 | import org.junit.Before; 28 | import org.junit.Test; 29 | 30 | import java.io.File; 31 | import java.util.Arrays; 32 | import java.util.List; 33 | import java.util.Map; 34 | import java.util.Set; 35 | import java.util.concurrent.TimeUnit; 36 | 37 | import static org.assertj.core.api.Assertions.assertThat; 38 | import static org.assertj.core.api.Assertions.fail; 39 | 40 | /** 41 | * @author Clement Escoffier 42 | */ 43 | public class VertxStacksTest { 44 | 45 | private static final List BASE = Arrays.asList( 46 | "io.vertx:vertx-dropwizard-metrics:jar", 47 | "io.vertx:vertx-reactive-streams:jar", 48 | "io.vertx:vertx-rx-java2:jar" 49 | ); 50 | 51 | 52 | private File root = new File("target/stack"); 53 | 54 | @Before 55 | public void setUp() { 56 | FileUtils.delete(root); 57 | Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !root.exists()); 58 | String vertxVersion = new VersionCommand().getVersion(); 59 | assertThat(vertxVersion).isNotEmpty(); 60 | System.setProperty("vertx.version", vertxVersion); 61 | } 62 | 63 | @After 64 | public void tearDown() { 65 | System.clearProperty("vertx.version"); 66 | } 67 | 68 | /** 69 | * This tests checks that all our dependencies converge to the same version. 70 | */ 71 | @Test 72 | public void testConvergence() { 73 | // Prepare the stack - use full stack, include everything 74 | Stack stack = Stack.fromDescriptor(new File("target/vertx-stack/vertx-stack-full.json")); 75 | // Stack stack = new Stack().addDependency(new Dependency("io.vertx", "vertx-core", "5.0.0-SNAPSHOT")); 76 | stack.getDependencies() 77 | .forEach(d -> d.setIncluded(true)); 78 | 79 | StackResolution resolution = new StackResolution(stack, root, 80 | new StackResolutionOptions().setFailOnConflicts(true).setCacheDisabled(true)); 81 | Map resolved = resolution.resolve(gav -> { 82 | // Check we don't have loggers in the distrib 83 | return !gav.startsWith("log4j:log4j") && !gav.startsWith("org.apache.logging.log4j:"); 84 | }); 85 | assertThat(resolved).isNotEmpty(); 86 | } 87 | 88 | @Test 89 | public void testTheResolutionOfTheWebStack() { 90 | Stack stack = Stack.fromDescriptor(new File("src/test/resources/stacks/vertx-web-stack.json")); 91 | 92 | StackResolution resolution = new StackResolution(stack, root, 93 | new StackResolutionOptions().setFailOnConflicts(true)); 94 | Map resolved = resolution.resolve(); 95 | assertThat(resolved).isNotEmpty(); 96 | } 97 | 98 | @Test 99 | public void testTheCoreWithoutNettyBufferStack() { 100 | Stack stack = Stack.fromDescriptor(new File("src/test/resources/stacks/vertx-core-only.json")); 101 | 102 | StackResolution resolution = new StackResolution(stack, root, 103 | new StackResolutionOptions().setFailOnConflicts(true)); 104 | Map resolved = resolution.resolve(); 105 | assertThat(resolved).isNotEmpty().doesNotContainKey("io.netty:netty-buffer"); 106 | } 107 | 108 | private void setUpBaseStack(Stack stack) { 109 | stack.getDependencies() 110 | .filter(dependency -> wasPartOfTheBaseStack(dependency.getManagementKey())) 111 | .forEach(dependency -> dependency.setIncluded(true)); 112 | } 113 | 114 | private void tearDownBaseStack(Stack stack) { 115 | stack.getDependencies() 116 | .filter(dependency -> wasPartOfTheBaseStack(dependency.getManagementKey())) 117 | .forEach(dependency -> dependency.setIncluded(false)); 118 | } 119 | 120 | private boolean wasPartOfTheBaseStack(String gacv) { 121 | return BASE.contains(gacv); 122 | } 123 | 124 | private VertxStacksTest hasKeysStartingBy(Map files, String k) { 125 | if (!containsKeyStartingByPrefix(files.keySet(), k)) { 126 | fail("Expected to have a key starting with '" + k + "' in " + files.keySet()); 127 | return this; 128 | } 129 | return this; 130 | } 131 | 132 | private VertxStacksTest doNotHaveKeysStartingBy(Map files, String k) { 133 | if (containsKeyStartingByPrefix(files.keySet(), k)) { 134 | fail("Expected to not have a key starting with '" + k + "' in " + files.keySet()); 135 | return this; 136 | } 137 | return this; 138 | } 139 | 140 | private VertxStacksTest ensureThatAllFilesExist(Map files) { 141 | for (File f : files.values()) { 142 | assertThat(f).isFile(); 143 | } 144 | return this; 145 | } 146 | 147 | private boolean containsKeyStartingByPrefix(Set keys, String prefix) { 148 | for (String k : keys) { 149 | if (k.startsWith(prefix)) { 150 | return true; 151 | } 152 | } 153 | return false; 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/CacheTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import io.vertx.stack.model.Artifact; 20 | import io.vertx.stack.resolver.ResolutionOptions; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.nio.file.Files; 27 | import java.util.Arrays; 28 | import java.util.Collections; 29 | import java.util.List; 30 | import java.util.Optional; 31 | 32 | import static org.assertj.core.api.Assertions.assertThat; 33 | 34 | /** 35 | * @author Clement Escoffier 36 | */ 37 | public class CacheTest { 38 | 39 | private Cache cache; 40 | private File cacheFile; 41 | 42 | static File TEMP_FILE; 43 | 44 | static { 45 | try { 46 | TEMP_FILE = File.createTempFile("acme", ".jar"); 47 | } catch (IOException e) { 48 | throw new IllegalStateException(e); 49 | } 50 | } 51 | 52 | @Before 53 | public void setUp() throws IOException { 54 | cacheFile = new File("target/test-cache/cache.json"); 55 | if (cacheFile.isFile()) { 56 | Files.delete(cacheFile.toPath()); 57 | } 58 | 59 | cache = new Cache(false, false, cacheFile); 60 | } 61 | 62 | @Test 63 | public void testCachingOfReleaseAndUpdate() { 64 | String gacv = "org.acme:acme:jar:1.0"; 65 | ResolutionOptions options = new ResolutionOptions(); 66 | List list = cache.get(gacv, options); 67 | assertThat(list).isNull(); 68 | 69 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0").setFile(TEMP_FILE); 70 | Artifact artifact2 = new Artifact("org.acme:acme-dep:jar:1.0").setFile(TEMP_FILE); 71 | 72 | cache.put(gacv, options, Collections.singletonList(artifact)); 73 | list = cache.get(gacv, options); 74 | assertThat(list).hasSize(1); 75 | 76 | cache.put(gacv, options, Collections.singletonList(artifact)); 77 | list = cache.get(gacv, options); 78 | assertThat(list).hasSize(1); 79 | 80 | cache.put(gacv, options, Arrays.asList(artifact, artifact2)); 81 | list = cache.get(gacv, options); 82 | assertThat(list).hasSize(2); 83 | } 84 | 85 | @Test 86 | public void testCachingOfSnapshotAndUpdate() { 87 | String gacv = "org.acme:acme:jar:1.0-SNAPSHOT"; 88 | ResolutionOptions options = new ResolutionOptions(); 89 | List list = cache.get(gacv, options); 90 | assertThat(list).isNull(); 91 | 92 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0-SNAPSHOT").setFile(TEMP_FILE); 93 | Artifact artifact2 = new Artifact("org.acme:acme-dep:jar:1.0-SNAPSHOT").setFile(TEMP_FILE); 94 | 95 | cache.put(gacv, options, Collections.singletonList(artifact)); 96 | list = cache.get(gacv, options); 97 | assertThat(list).hasSize(1); 98 | 99 | cache.put(gacv, options, Collections.singletonList(artifact)); 100 | list = cache.get(gacv, options); 101 | assertThat(list).hasSize(1); 102 | 103 | cache.put(gacv, options, Arrays.asList(artifact, artifact2)); 104 | list = cache.get(gacv, options); 105 | assertThat(list).hasSize(2); 106 | } 107 | 108 | 109 | @Test 110 | public void testDisabledCache() throws IOException { 111 | String gacv = "org.acme:acme:jar:1.0"; 112 | cache = new Cache(true, false, cacheFile); 113 | ResolutionOptions options = new ResolutionOptions(); 114 | List list = cache.get(gacv, options); 115 | assertThat(list).isNull(); 116 | 117 | File file = File.createTempFile("acme", ".jar"); 118 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0").setFile(file); 119 | 120 | cache.put(gacv, options, Collections.singletonList(artifact)); 121 | list = cache.get(gacv, options); 122 | assertThat(list).isNull(); 123 | } 124 | 125 | @Test 126 | public void testCacheDisabledForSnapshots() { 127 | String gacv = "org.acme:acme:jar:1.0-SNAPSHOT"; 128 | cache = new Cache(false, true, cacheFile); 129 | ResolutionOptions options = new ResolutionOptions(); 130 | List list = cache.get(gacv, options); 131 | assertThat(list).isNull(); 132 | 133 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0-SNAPSHOT").setFile(TEMP_FILE); 134 | 135 | cache.put(gacv, options, Collections.singletonList(artifact)); 136 | list = cache.get(gacv, options); 137 | assertThat(list).isNull(); 138 | } 139 | 140 | @Test 141 | public void testWithInvalidArtifact() { 142 | String gacv = "org.acme:acme:jar:1.0"; 143 | ResolutionOptions options = new ResolutionOptions(); 144 | List list = cache.get(gacv, options); 145 | assertThat(list).isNull(); 146 | 147 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0").setFile(new File("does not exist.jar")); 148 | 149 | cache.put(gacv, options, Collections.singletonList(artifact)); 150 | list = cache.get(gacv, options); 151 | assertThat(list).isNull(); 152 | } 153 | 154 | @Test 155 | public void testWithEmptyResolution() { 156 | String gacv = "org.acme:acme:jar:1.0"; 157 | ResolutionOptions options = new ResolutionOptions(); 158 | List list = cache.get(gacv, options); 159 | assertThat(list).isNull(); 160 | cache.put(gacv, options, Collections.emptyList()); 161 | list = cache.get(gacv, options); 162 | assertThat(list).isNull(); 163 | } 164 | 165 | @Test 166 | public void testCacheReloading() { 167 | String gacv = "org.acme:acme:jar:1.0"; 168 | ResolutionOptions options = new ResolutionOptions(); 169 | List list = cache.get(gacv, options); 170 | assertThat(list).isNull(); 171 | 172 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0").setFile(TEMP_FILE); 173 | 174 | cache.put(gacv, options, Collections.singletonList(artifact)); 175 | list = cache.get(gacv, options); 176 | assertThat(list).hasSize(1); 177 | cache.writeCacheOnFile(); 178 | 179 | cache = new Cache(false, false, cacheFile); 180 | 181 | list = cache.get(gacv, options); 182 | assertThat(list).hasSize(1); 183 | } 184 | 185 | @Test 186 | public void testSnapshotEviction() { 187 | String gacv = "org.acme:acme:jar:1.0-SNAPSHOT"; 188 | ResolutionOptions options = new ResolutionOptions(); 189 | List list = cache.get(gacv, options); 190 | assertThat(list).isNull(); 191 | 192 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0-SNAPSHOT").setFile(TEMP_FILE); 193 | 194 | cache.put(gacv, options, Collections.singletonList(artifact)); 195 | list = cache.get(gacv, options); 196 | assertThat(list).hasSize(1); 197 | 198 | Optional entry = cache.find(gacv, options); 199 | assertThat(entry).isPresent(); 200 | entry.get().setInsertionTime(System.currentTimeMillis() - 25 * 60 * 60 * 1000); 201 | 202 | list = cache.get(gacv, options); 203 | assertThat(list).isNull(); 204 | } 205 | 206 | @Test 207 | public void testNonSnapshotEviction() { 208 | String gacv = "org.acme:acme:jar:1.0-SNAPSHOT"; 209 | ResolutionOptions options = new ResolutionOptions(); 210 | List list = cache.get(gacv, options); 211 | assertThat(list).isNull(); 212 | 213 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0-SNAPSHOT").setFile(TEMP_FILE); 214 | 215 | cache.put(gacv, options, Collections.singletonList(artifact)); 216 | list = cache.get(gacv, options); 217 | assertThat(list).hasSize(1); 218 | 219 | Optional entry = cache.find(gacv, options); 220 | assertThat(entry).isPresent(); 221 | entry.get().setInsertionTime(System.currentTimeMillis() - 22 * 60 * 60 * 1000); 222 | 223 | list = cache.get(gacv, options); 224 | assertThat(list).hasSize(1); 225 | } 226 | 227 | @Test 228 | public void testCachingUsingDifferentResolutionOption() { 229 | String gacv = "org.acme:acme:jar:1.0"; 230 | ResolutionOptions options = new ResolutionOptions(); 231 | List list = cache.get(gacv, options); 232 | assertThat(list).isNull(); 233 | 234 | Artifact artifact = new Artifact("org.acme:acme:jar:1.0").setFile(TEMP_FILE); 235 | 236 | cache.put(gacv, options, Collections.singletonList(artifact)); 237 | list = cache.get(gacv, options); 238 | assertThat(list).hasSize(1); 239 | 240 | options = new ResolutionOptions().setWithTransitive(false); 241 | list = cache.get(gacv, options); 242 | assertThat(list).isNull(); 243 | 244 | cache.put(gacv, options, Collections.singletonList(artifact)); 245 | list = cache.get(gacv, options); 246 | assertThat(list).hasSize(1); 247 | assertThat(cache.size()).isEqualTo(2); 248 | 249 | options = new ResolutionOptions().setWithTransitive(true).addExclusion("org.acme:transitive"); 250 | list = cache.get(gacv, options); 251 | assertThat(list).isNull(); 252 | 253 | cache.put(gacv, options, Collections.singletonList(artifact)); 254 | list = cache.get(gacv, options); 255 | assertThat(list).hasSize(1); 256 | assertThat(cache.size()).isEqualTo(3); 257 | } 258 | 259 | @Test 260 | public void testDeserializationOfViaArtifact() { 261 | ResolutionOptions resolutionOptions = new ResolutionOptions(); 262 | Artifact root = new Artifact("org.acme:acme:jar:1.0").setFile(TEMP_FILE); 263 | String gacv = "org.acme:transitive:jar:1.1"; 264 | Artifact transitive = new Artifact(gacv, root).setFile(TEMP_FILE); 265 | cache.put(gacv, resolutionOptions, Collections.singletonList(transitive)); 266 | cache.writeCacheOnFile(); 267 | 268 | cache = new Cache(false, false, cacheFile); 269 | List deserialized = cache.get(gacv, resolutionOptions); 270 | assertThat(deserialized).hasSize(1); 271 | assertThat(deserialized.get(0).getVia()).isEqualTo(root); 272 | } 273 | 274 | } 275 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.nio.file.*; 22 | import java.nio.file.attribute.BasicFileAttributes; 23 | 24 | /** 25 | * @author Clement Escoffier 26 | */ 27 | public class FileUtils { 28 | 29 | public static void write(File file, String content) { 30 | try { 31 | Files.write(file.toPath(), content.getBytes()); 32 | } catch (IOException ex) { 33 | throw new RuntimeException(ex); 34 | } 35 | } 36 | 37 | public static void deleteQuietly(File file) { 38 | try { 39 | Files.deleteIfExists(file.toPath()); 40 | } catch (Exception e) { 41 | // Ignore it. 42 | } 43 | } 44 | 45 | public static void copyFile(File source, File target) { 46 | Path s = source.toPath(); 47 | Path t = target.toPath(); 48 | try { 49 | Files.copy(s, t, StandardCopyOption.REPLACE_EXISTING); 50 | } catch (IOException e) { 51 | throw new RuntimeException(e); 52 | } 53 | } 54 | 55 | public static String getExtension(File file) { 56 | int index = file.getName().lastIndexOf("."); 57 | if (index == -1) { 58 | return ""; 59 | } else { 60 | return file.getName().substring(index + 1); 61 | } 62 | } 63 | 64 | public static void delete(File file) { 65 | if (file.isFile()) { 66 | deleteQuietly(file); 67 | } else if (file.isDirectory()) { 68 | Path directory = file.toPath(); 69 | try { 70 | Files.walkFileTree(directory, new SimpleFileVisitor() { 71 | @Override 72 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 73 | Files.delete(file); 74 | return FileVisitResult.CONTINUE; 75 | } 76 | 77 | @Override 78 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 79 | Files.delete(dir); 80 | return FileVisitResult.CONTINUE; 81 | } 82 | }); 83 | } catch (IOException e) { 84 | throw new IllegalStateException(e); 85 | } 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/FilteringTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Collections; 22 | 23 | import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; 24 | 25 | 26 | /** 27 | * @author Clement Escoffier 28 | */ 29 | public class FilteringTest { 30 | 31 | @Test 32 | public void testFilteringWithoutVariables() { 33 | String out = Filtering.filter("hello", Collections.emptyMap()); 34 | assertThat(out).isEqualTo("hello"); 35 | } 36 | 37 | @Test 38 | public void testFilteringWithoutPlaceholders() { 39 | String out = Filtering.filter("hello", new FluentMap<>().add("key", "value")); 40 | assertThat(out).isEqualTo("hello"); 41 | } 42 | 43 | @Test 44 | public void testFilteringWithNonMatchingVariables() { 45 | String out = Filtering.filter("hello ${nope}", new FluentMap<>().add("key", "value")); 46 | assertThat(out).isEqualTo("hello ${nope}"); 47 | } 48 | 49 | @Test 50 | public void testFilteringWithReplacement() { 51 | String out = Filtering.filter("hello ${world}", new FluentMap<>().add("world", "vert.x")); 52 | assertThat(out).isEqualTo("hello vert.x"); 53 | } 54 | 55 | @Test 56 | public void testFilteringWithPartialReplacement() { 57 | String out = Filtering.filter("hello ${world} ${period}", new FluentMap<>().add("world", "vert.x")); 58 | assertThat(out).isEqualTo("hello vert.x ${period}"); 59 | } 60 | 61 | @Test 62 | public void testFilteringWithNestedReplacement() { 63 | String out = Filtering.filter("hello ${world} ${period}", new FluentMap<>() 64 | .add("name", "vert.x") 65 | .add("world", "${name}")); 66 | assertThat(out).isEqualTo("hello vert.x ${period}"); 67 | } 68 | 69 | @Test 70 | public void testFilteringWithUnfinishedVariables() { 71 | String out = Filtering.filter("hello ${world} ${per ", new FluentMap<>() 72 | .add("name", "vert.x") 73 | .add("world", "${name}")); 74 | assertThat(out).isEqualTo("hello vert.x ${per "); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/FluentMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.util.LinkedHashMap; 20 | 21 | /** 22 | * @author Clement Escoffier 23 | */ 24 | public class FluentMap extends LinkedHashMap { 25 | 26 | public FluentMap add(K k, V v) { 27 | put(k, v); 28 | return this; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/LocalArtifact.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.util.*; 22 | 23 | /** 24 | * @author Clement Escoffier 25 | */ 26 | public class LocalArtifact { 27 | 28 | public static final String MAIN_ARTIFACT_CLASSIFIER = "MAIN"; 29 | private final String groupId; 30 | private final String artifactId; 31 | private final String version; 32 | private String packaging; 33 | private Map files = new HashMap<>(); 34 | private LocalArtifact parent; 35 | private List dependencies = new ArrayList<>(); 36 | private List dependencyManagement = new ArrayList<>(); 37 | private Map properties = new LinkedHashMap<>(); 38 | private boolean inheritGroupId; 39 | private boolean inheritVersion; 40 | 41 | public LocalArtifact(String groupId, String artifactId, String version) { 42 | Objects.requireNonNull(groupId); 43 | Objects.requireNonNull(artifactId); 44 | Objects.requireNonNull(version); 45 | this.groupId = groupId; 46 | this.artifactId = artifactId; 47 | this.version = version; 48 | } 49 | 50 | public LocalArtifact inheritGroupId() { 51 | this.inheritGroupId = true; 52 | return this; 53 | } 54 | 55 | public LocalArtifact inheritVersion() { 56 | this.inheritVersion = true; 57 | return this; 58 | } 59 | 60 | public LocalArtifact packaging(String type) { 61 | this.packaging = type; 62 | return this; 63 | } 64 | 65 | public LocalArtifact file(File file) { 66 | this.files.put(MAIN_ARTIFACT_CLASSIFIER, file); 67 | return this; 68 | } 69 | 70 | public LocalArtifact file(File file, String classifier) { 71 | this.files.put(classifier, file); 72 | return this; 73 | } 74 | 75 | public LocalArtifact parent(LocalArtifact parent) { 76 | this.parent = parent; 77 | return this; 78 | } 79 | 80 | public LocalArtifact parent(String groupId, String artifactId, String version) { 81 | this.parent = new LocalArtifact(groupId, artifactId, version); 82 | return this; 83 | } 84 | 85 | public LocalArtifact addDependency(LocalDependency dependency) { 86 | dependencies.add(dependency); 87 | return this; 88 | } 89 | 90 | public LocalArtifact addDependencyToDependencyManagement(LocalDependency dependency) { 91 | dependencyManagement.add(dependency); 92 | return this; 93 | } 94 | 95 | public LocalArtifact addProperty(String key, String value) { 96 | properties.put(key, value); 97 | return this; 98 | } 99 | 100 | public File getArtifactDirectory(File root) { 101 | return new File(root, groupId.replace(".", File.separator) + File.separator + artifactId 102 | + File.separator + version); 103 | } 104 | 105 | public File getPomFile(File root) { 106 | return new File(getArtifactDirectory(root), artifactId + "-" + version + ".pom"); 107 | } 108 | 109 | public File getFile(File root) { 110 | String ext = FileUtils.getExtension(files.get(MAIN_ARTIFACT_CLASSIFIER)); 111 | return new File(getArtifactDirectory(root), artifactId + "-" + version + "." + ext); 112 | } 113 | 114 | public File getFile(String classifier, File root) { 115 | String ext = FileUtils.getExtension(files.get(classifier)); 116 | return new File(getArtifactDirectory(root), artifactId + "-" + version + "-" + classifier + "." + ext); 117 | } 118 | 119 | public String toPom() { 120 | StringBuilder builder = new StringBuilder(); 121 | line(builder, 0, ""); 125 | 126 | line(builder, 1, "4.0.0"); 127 | 128 | // Coordinates 129 | if (!inheritGroupId) { 130 | line(builder, 1, "" + groupId + ""); 131 | } 132 | line(builder, 1, "" + artifactId + ""); 133 | if (!inheritVersion) { 134 | line(builder, 1, "" + version + ""); 135 | } 136 | 137 | // Parent if any 138 | if (parent != null) { 139 | line(builder, 1, ""); 140 | line(builder, 2, "" + parent.groupId + ""); 141 | line(builder, 2, "" + parent.artifactId + ""); 142 | line(builder, 2, "" + parent.version + ""); 143 | line(builder, 1, ""); 144 | } 145 | 146 | if (packaging != null) { 147 | line(builder, 1, "" + packaging + ""); 148 | } 149 | 150 | if (!properties.isEmpty()) { 151 | line(builder, 1, ""); 152 | properties.forEach((k, v) -> line(builder, 2, "<" + k + ">" + v + "")); 153 | line(builder, 1, ""); 154 | } 155 | 156 | if (!dependencyManagement.isEmpty()) { 157 | line(builder, 1, ""); 158 | dependencyManagement.stream().forEach(dep -> builder.append(dep.toDependency(2))); 159 | line(builder, 1, ""); 160 | } 161 | 162 | if (!dependencies.isEmpty()) { 163 | line(builder, 1, ""); 164 | dependencies.stream().forEach(dep -> builder.append(dep.toDependency(2))); 165 | line(builder, 1, ""); 166 | } 167 | 168 | line(builder, 0, ""); 169 | return builder.toString(); 170 | } 171 | 172 | private void line(StringBuilder builder, int indent, String line) { 173 | builder.append(PomUtils.indentation(indent)).append(line).append("\n"); 174 | } 175 | 176 | public Map getFiles() { 177 | return files; 178 | } 179 | 180 | public String gav() { 181 | return groupId + ":" + artifactId + ":" + version; 182 | } 183 | 184 | public LocalArtifact generateMainArtifact() { 185 | try { 186 | File tmp = File.createTempFile("local-artifact-" + artifactId, ".txt"); 187 | FileUtils.write(tmp, gav()); 188 | return file(tmp).packaging("txt"); 189 | } catch (IOException e) { 190 | throw new IllegalStateException(e); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/LocalDependency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Objects; 22 | 23 | /** 24 | * @author Clement Escoffier 25 | */ 26 | public class LocalDependency { 27 | 28 | private final String groupId; 29 | private final String artifactId; 30 | private final String version; 31 | private String type; 32 | private List exclusions = new ArrayList<>(); 33 | 34 | private String scope = "compile"; 35 | private boolean optional = false; 36 | private String classifier; 37 | 38 | public LocalDependency(String groupId, String artifactId, String version) { 39 | this.groupId = groupId; 40 | this.artifactId = artifactId; 41 | Objects.requireNonNull(groupId); 42 | Objects.requireNonNull(artifactId); 43 | this.version = version; 44 | } 45 | 46 | public LocalDependency(String groupId, String artifactId) { 47 | this(groupId, artifactId, null); 48 | } 49 | 50 | public LocalDependency type(String type) { 51 | this.type = type; 52 | return this; 53 | } 54 | 55 | public LocalDependency classifier(String c) { 56 | this.classifier = c; 57 | return this; 58 | } 59 | 60 | public LocalDependency optional(boolean opt) { 61 | this.optional = opt; 62 | return this; 63 | } 64 | 65 | public LocalDependency scope(String scope) { 66 | this.scope = scope; 67 | return this; 68 | } 69 | 70 | public LocalDependency addExclusion(String groupId, String artifactId) { 71 | this.exclusions.add(new Exclusion(groupId, artifactId)); 72 | return this; 73 | } 74 | 75 | private class Exclusion { 76 | 77 | private final String groupId; 78 | private final String artifactId; 79 | 80 | public Exclusion(String groupId, String artifactId) { 81 | this.groupId = groupId; 82 | this.artifactId = artifactId; 83 | } 84 | } 85 | 86 | public String toDependency(int indent) { 87 | StringBuilder builder = new StringBuilder(); 88 | builder.append(PomUtils.indentation(indent)).append("\n"); 89 | builder.append(PomUtils.indentation(indent + 1)).append("").append(groupId).append("\n"); 90 | builder.append(PomUtils.indentation(indent + 1)).append("").append(artifactId).append("\n"); 91 | if (version != null) { 92 | builder.append(PomUtils.indentation(indent + 1)).append("").append(version).append("\n"); 93 | } 94 | if (optional) { 95 | builder.append(PomUtils.indentation(indent + 1)).append("true\n"); 96 | } 97 | if (type != null) { 98 | builder.append(PomUtils.indentation(indent + 1)).append("").append(type).append("\n"); 99 | } 100 | if (scope != null) { 101 | builder.append(PomUtils.indentation(indent + 1)).append("").append(scope).append("\n"); 102 | } 103 | if (classifier != null) { 104 | builder.append(PomUtils.indentation(indent + 1)).append("").append(classifier).append("\n"); 105 | } 106 | if (! exclusions.isEmpty()) { 107 | builder.append(PomUtils.indentation(indent + 1)).append("\n"); 108 | for (Exclusion exclusion : exclusions) { 109 | builder.append(PomUtils.indentation(indent + 2)).append("\n"); 110 | builder.append(PomUtils.indentation(indent + 3)).append("").append(exclusion.groupId).append("\n"); 111 | builder.append(PomUtils.indentation(indent + 3)).append("").append(exclusion.artifactId).append("\n"); 112 | builder.append(PomUtils.indentation(indent + 2)).append("\n"); 113 | } 114 | builder.append(PomUtils.indentation(indent + 1)).append("\n"); 115 | } 116 | builder.append(PomUtils.indentation(indent)).append("\n"); 117 | return builder.toString(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/LocalRepoBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | import io.vertx.core.internal.logging.Logger; 20 | import io.vertx.core.internal.logging.LoggerFactory; 21 | 22 | import java.io.File; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | /** 28 | * @author Clement Escoffier 29 | */ 30 | public class LocalRepoBuilder { 31 | 32 | private final static Logger LOGGER = LoggerFactory.getLogger(LocalRepoBuilder.class.getName()); 33 | 34 | private final File output; 35 | private List artifacts = new ArrayList<>(); 36 | 37 | public LocalRepoBuilder(File output) { 38 | this.output = output; 39 | } 40 | 41 | public LocalRepoBuilder addArtifact(LocalArtifact artifact) { 42 | this.artifacts.add(artifact); 43 | return this; 44 | } 45 | 46 | public void build() { 47 | build(true); 48 | } 49 | 50 | public void build(boolean clean) { 51 | if (output.isDirectory() && clean) { 52 | LOGGER.info("Deleting " + output.getAbsolutePath()); 53 | FileUtils.deleteQuietly(output); 54 | output.mkdirs(); 55 | } 56 | 57 | // Install all artifacts 58 | artifacts.stream().forEach(artifact -> { 59 | File directory = artifact.getArtifactDirectory(output); 60 | directory.mkdirs(); 61 | 62 | // Copy pom 63 | File pom = artifact.getPomFile(output); 64 | FileUtils.write(pom, artifact.toPom()); 65 | 66 | // Copy files 67 | for (Map.Entry entry : artifact.getFiles().entrySet()) { 68 | if (entry.getKey().equals(LocalArtifact.MAIN_ARTIFACT_CLASSIFIER)) { 69 | FileUtils.copyFile(entry.getValue(), artifact.getFile(output)); 70 | } else { 71 | FileUtils.copyFile(entry.getValue(), artifact.getFile(entry.getKey(), output)); 72 | } 73 | } 74 | 75 | LOGGER.info("The artifact " + artifact.gav() + " has been installed in the local repository"); 76 | }); 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /stack-manager/src/test/java/io/vertx/stack/utils/PomUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.stack.utils; 18 | 19 | /** 20 | * @author Clement Escoffier 21 | */ 22 | public class PomUtils { 23 | 24 | public static String indentation(int numberOfIndent) { 25 | StringBuilder builder = new StringBuilder(); 26 | for (int i = 0; i < numberOfIndent; i++) { 27 | builder.append("\t"); 28 | } 29 | return builder.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /stack-manager/src/test/resources/stacks/core-with-system-variable.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "groupId": "io.vertx", 5 | "artifactId": "vertx-core", 6 | "version": "${vertx.version}", 7 | "included" : true 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /stack-manager/src/test/resources/stacks/core-with-variable.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "vertx.version": "3.1.0" 4 | }, 5 | "dependencies": [ 6 | { 7 | "groupId": "io.vertx", 8 | "artifactId": "vertx-core", 9 | "version": "${vertx.version}", 10 | "included": true 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /stack-manager/src/test/resources/stacks/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "groupId": "io.vertx", 5 | "artifactId": "vertx-core", 6 | "version": "3.1.0", 7 | "included" : true 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /stack-manager/src/test/resources/stacks/vertx-core-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "groupId": "io.vertx", 5 | "artifactId": "vertx-core", 6 | "version": "3.1.0", 7 | "included" : true, 8 | "exclusions": [ 9 | { 10 | "groupId": "io.netty", 11 | "artifactId": "netty-buffer" 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /stack-manager/src/test/resources/stacks/vertx-web-stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "groupId": "io.vertx", 5 | "artifactId": "vertx-core", 6 | "version": "${vertx.version}", 7 | "included": true 8 | }, 9 | { 10 | "groupId": "io.vertx", 11 | "artifactId": "vertx-hazelcast", 12 | "version": "${vertx.version}", 13 | "included": true 14 | }, 15 | { 16 | "groupId": "io.vertx", 17 | "artifactId": "vertx-lang-groovy", 18 | "version": "${vertx.version}", 19 | "included": true 20 | }, 21 | { 22 | "groupId": "io.vertx", 23 | "artifactId": "vertx-service-proxy", 24 | "version": "${vertx.version}", 25 | "included": true 26 | }, 27 | { 28 | "groupId": "io.vertx", 29 | "artifactId": "vertx-http-service-factory", 30 | "version": "${vertx.version}", 31 | "included": false 32 | }, 33 | { 34 | "groupId": "io.vertx", 35 | "artifactId": "vertx-dropwizard-metrics", 36 | "version": "${vertx.version}", 37 | "included": false 38 | }, 39 | { 40 | "groupId": "io.vertx", 41 | "artifactId": "vertx-maven-service-factory", 42 | "version": "${vertx.version}", 43 | "included": false 44 | }, 45 | { 46 | "groupId": "io.vertx", 47 | "artifactId": "vertx-reactive-streams", 48 | "version": "${vertx.version}", 49 | "included": false 50 | }, 51 | { 52 | "groupId": "io.vertx", 53 | "artifactId": "vertx-service-factory", 54 | "version": "${vertx.version}", 55 | "included": false 56 | }, 57 | { 58 | "groupId": "io.vertx", 59 | "artifactId": "vertx-auth-common", 60 | "version": "${vertx.version}", 61 | "included": false 62 | }, 63 | { 64 | "groupId": "io.vertx", 65 | "artifactId": "vertx-auth-jwt", 66 | "version": "${vertx.version}", 67 | "included": false 68 | }, 69 | { 70 | "groupId": "io.vertx", 71 | "artifactId": "vertx-jdbc-client", 72 | "version": "${vertx.version}", 73 | "included": false 74 | }, 75 | { 76 | "groupId": "io.vertx", 77 | "artifactId": "vertx-consul-client", 78 | "version": "${vertx.version}", 79 | "included": false 80 | }, 81 | { 82 | "groupId": "io.vertx", 83 | "artifactId": "vertx-mongo-client", 84 | "version": "${vertx.version}", 85 | "included": false 86 | }, 87 | { 88 | "groupId": "io.vertx", 89 | "artifactId": "vertx-reactive-streams", 90 | "version": "${vertx.version}", 91 | "included": false 92 | }, 93 | { 94 | "groupId": "io.vertx", 95 | "artifactId": "vertx-redis-client", 96 | "version": "${vertx.version}", 97 | "included": false 98 | }, 99 | { 100 | "groupId": "io.vertx", 101 | "artifactId": "vertx-unit", 102 | "version": "${vertx.version}", 103 | "included": false 104 | }, 105 | { 106 | "groupId": "io.vertx", 107 | "artifactId": "vertx-web", 108 | "version": "${vertx.version}", 109 | "included": true 110 | }, 111 | { 112 | "groupId": "io.vertx", 113 | "artifactId": "vertx-web-templ-handlebars", 114 | "version": "${vertx.version}", 115 | "classifier": "shaded", 116 | "transitive": false, 117 | "included": true 118 | }, 119 | { 120 | "groupId": "io.vertx", 121 | "artifactId": "vertx-web-templ-pug", 122 | "version": "${vertx.version}", 123 | "classifier": "shaded", 124 | "transitive": false, 125 | "included": true 126 | }, 127 | { 128 | "groupId": "io.vertx", 129 | "artifactId": "vertx-web-templ-mvel", 130 | "version": "${vertx.version}", 131 | "classifier": "shaded", 132 | "transitive": false, 133 | "included": true 134 | }, 135 | { 136 | "groupId": "io.vertx", 137 | "artifactId": "vertx-web-templ-thymeleaf", 138 | "version": "${vertx.version}", 139 | "classifier": "shaded", 140 | "transitive": false, 141 | "included": true 142 | }, 143 | { 144 | "groupId": "io.vertx", 145 | "artifactId": "vertx-stomp", 146 | "version": "${vertx.version}", 147 | "included": false 148 | }, 149 | { 150 | "groupId": "io.vertx", 151 | "artifactId": "vertx-shell", 152 | "version": "${vertx.version}", 153 | "included": false 154 | }, 155 | { 156 | "groupId": "io.vertx", 157 | "artifactId": "vertx-sync", 158 | "version": "${vertx.version}", 159 | "included": false 160 | } 161 | ] 162 | } 163 | --------------------------------------------------------------------------------