├── .gitattributes
├── .github
└── workflows
│ └── linux-build-release.yml
├── .gitignore
├── LICENSE.txt
├── README.md
├── RELEASE_NOTES.md
├── build.gradle
├── gradle
├── integration-test.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── integrationTest
└── groovy
│ └── com
│ └── bmuschko
│ └── gradle
│ └── cargo
│ └── util
│ ├── AbstractIntegrationSpec.groovy
│ ├── ConfigFileIntegrationSpec.groovy
│ ├── DefaultDeployableSpec.groovy
│ ├── DeployableIntegrationSpec.groovy
│ ├── InstallerUrlIntegrationSpec.groovy
│ ├── LocallyInstalledContainerIntegrationSpec.groovy
│ └── fixture
│ ├── AbstractWarFixture.groovy
│ ├── HelloWorldServletWarFixture.groovy
│ ├── ProjectFixture.groovy
│ ├── TextResourceFactoryJarFixture.groovy
│ └── TextResourceLoaderServletWarFixture.groovy
├── main
└── groovy
│ └── com
│ └── bmuschko
│ └── gradle
│ └── cargo
│ ├── CargoBasePlugin.groovy
│ ├── CargoPlugin.groovy
│ ├── DeployableType.groovy
│ ├── DeployableTypeFactory.groovy
│ ├── convention
│ ├── BinFile.groovy
│ ├── CargoLocalTaskConvention.groovy
│ ├── CargoPluginExtension.groovy
│ ├── CargoRemoteTaskConvention.groovy
│ ├── ConfigFile.groovy
│ ├── ContainerProperties.groovy
│ ├── Deployable.groovy
│ ├── SystemProperties.groovy
│ └── ZipUrlInstaller.groovy
│ ├── tasks
│ ├── AbstractCargoContainerTask.groovy
│ ├── daemon
│ │ ├── CargoDaemon.groovy
│ │ ├── CargoDaemonStart.groovy
│ │ └── CargoDaemonStop.groovy
│ ├── local
│ │ ├── CargoConfigureLocal.groovy
│ │ ├── CargoRedeployLocal.groovy
│ │ ├── CargoRunLocal.groovy
│ │ ├── CargoStartLocal.groovy
│ │ ├── CargoStopLocal.groovy
│ │ └── LocalCargoContainerTask.groovy
│ └── remote
│ │ ├── CargoDeployRemote.groovy
│ │ ├── CargoRedeployRemote.groovy
│ │ ├── CargoUndeployRemote.groovy
│ │ └── RemoteCargoContainerTask.groovy
│ └── util
│ ├── CargoAntLoggingListener.groovy
│ ├── DefaultFileUtil.groovy
│ ├── FileUtil.groovy
│ ├── LoggingHandler.groovy
│ └── ProjectInfoHelper.groovy
└── test
└── groovy
└── com
└── bmuschko
└── gradle
└── cargo
└── util
├── CargoAntLoggingListenerSpec.groovy
├── DefaultFileUtilSpec.groovy
├── DeployableTypeFactorySpec.groovy
└── LoggingHandlerSpec.groovy
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.bat text eol=crlf
2 | gradlew text eol=lf
--------------------------------------------------------------------------------
/.github/workflows/linux-build-release.yml:
--------------------------------------------------------------------------------
1 | name: Build and Release [Linux]
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | build:
6 | name: Build
7 | runs-on: ubuntu-18.04
8 | steps:
9 | - name: Checkout
10 | uses: actions/checkout@v1
11 | - name: Set up Java
12 | uses: actions/setup-java@v1
13 | with:
14 | java-version: 11
15 | - name: Compilation
16 | uses: eskatos/gradle-command-action@v1
17 | with:
18 | arguments: classes
19 | - name: Unit tests
20 | uses: eskatos/gradle-command-action@v1
21 | with:
22 | arguments: test
23 | - name: Integration tests
24 | uses: eskatos/gradle-command-action@v1
25 | with:
26 | arguments: integrationTest
27 | - name: Assemble artifact
28 | uses: eskatos/gradle-command-action@v1
29 | with:
30 | arguments: assemble
31 | - name: Store artifact
32 | uses: actions/upload-artifact@v2
33 | with:
34 | name: gradle-tomcat-plugin.jar
35 | path: build/libs/*.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | out
3 | *.iml
4 | *.ipr
5 | *.iws
6 | .idea
7 | .gradle
8 | /bin/
9 | /.project
10 | /.classpath
11 | /.settings
--------------------------------------------------------------------------------
/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 | # Gradle Cargo plugin [](https://github.com/bmuschko/gradle-cargo-plugin/actions?query=workflow%3A%22Build+and+Release+%5BLinux%5D%22)
2 |
3 | 
4 |
5 |
6 |
7 |
8 | Over the past couple of years this plugin has seen many releases. Thanks to everyone involved!
9 | Unfortunately, I don't have much time to contribute anymore. In practice this means far less activity,
10 | responsiveness on issues and new releases from my end.
11 | |
12 |
13 |
14 |
15 | I am
16 | actively looking for contributors
17 | willing to take on maintenance and implementation of the project. If you are interested and would love to see this
18 | plugin continue to thrive, shoot me a mail.
19 | |
20 |
21 |
22 |
23 | The plugin provides deployment capabilities for web applications to local and remote containers in any given
24 | Gradle build by leveraging the [Cargo Ant tasks](https://codehaus-cargo.github.io/cargo/Ant+support.html). The plugin supports WAR and EAR
25 | artifacts.
26 |
27 | The typical use case for this plugin is to support deployment during development. Keep in mind that Cargo uses hot deployment
28 | which over time fills up the PermGen memory of the JVM process running your container. Continuously deploying an artifact will
29 | inevitablity lead to a `java.lang.OutOfMemoryError`. Cargo does support container management capabilities (starting/stopping
30 | of remote containers) via the so-called [Cargo daemon](https://codehaus-cargo.github.io/cargo/Cargo+Daemon.html). However, in continuous deployment
31 | scenarios you often want to need perform more complex operations.
32 |
33 | ## Usage
34 |
35 | To use the plugin's functionality, you will need to add the its binary artifact to your build script's classpath and apply
36 | the plugin.
37 |
38 | ### Adding the plugin binary to the build
39 |
40 | The plugin JAR needs to be defined in the classpath of your build script. It is available on the Gradle plugin portal. The following code snippet
41 | shows an example on how to retrieve it with the `buildscript` syntax:
42 |
43 | buildscript {
44 | repositories {
45 | gradlePluginPortal()
46 | }
47 |
48 | dependencies {
49 | classpath 'com.bmuschko:gradle-cargo-plugin:2.9.0'
50 | }
51 | }
52 |
53 | ### Provided plugins
54 |
55 | The JAR file comes with two plugins:
56 |
57 |
58 |
59 | Plugin Identifier |
60 | Depends On |
61 | Type |
62 | Description |
63 |
64 |
65 | com.bmuschko.cargo-base |
66 | - |
67 | CargoBasePlugin |
68 | Provides Cargo custom task types, pre-configures classpath and deployables. |
69 |
70 |
71 | com.bmuschko.cargo |
72 | com.bmuschko.cargo-base |
73 | CargoPlugin |
74 | Provides a set of local and remote Cargo tasks and exposes extension for configuration. |
75 |
76 |
77 |
78 | The `com.bmuschko.cargo` plugin helps you get started quickly. If you only need to deal with a single container product, this is the
79 | preferrable option. Most plugin users will go with this option. To use the Cargo plugin, include the following code snippet
80 | in your build script:
81 |
82 | apply plugin: 'com.bmuschko.cargo'
83 |
84 | If you need full control over your deployment tasks, you will want to use the `com.bmuschko.cargo-base` plugin. The downside is that each task
85 | has to be configured individually in your build script. To use the Cargo base plugin, include the following code snippet
86 | in your build script:
87 |
88 | apply plugin: 'com.bmuschko.cargo-base'
89 |
90 | ### Configuring the Cargo version
91 |
92 | The `com.bmuschko.cargo-base` plugin already sets up the dependencies for Cargo. In order to do so, it chooses a default
93 | version of the libraries. Alternatively, you can define a custom version of the Cargo libraries. To do so, please use
94 | the `cargo` configuration name in your `dependencies` closure, and keep the below in mind:
95 | * Remote deployment functionality will only work with a Cargo version >= 1.1.0 due to a bug in the library (see [CARGO-962](https://codehaus-cargo.atlassian.net/browse/CARGO-962) for more information).
96 | * Setting configuration properties will only work with a Cargo version >= 1.9.10 due to missing feature in the library (see [CARGO-1578](https://codehaus-cargo.atlassian.net/browse/CARGO-1578) for more information).
97 | The following example demonstrates how to use the version 1.9.10 of the Cargo libraries:
98 |
99 | ```
100 | dependencies {
101 | def cargoVersion = '1.9.10'
102 | cargo "org.codehaus.cargo:cargo-core-uberjar:$cargoVersion",
103 | "org.codehaus.cargo:cargo-licensed-dtds:$cargoVersion",
104 | "org.codehaus.cargo:cargo-ant:$cargoVersion"
105 | }
106 | ```
107 |
108 | ## Tasks
109 |
110 | The `cargo` plugin pre-defines the following tasks out-of-the-box:
111 |
112 |
113 |
114 | Task Name |
115 | Depends On |
116 | Type |
117 | Description |
118 |
119 |
120 | cargoDeployRemote |
121 | - |
122 | CargoDeployRemote |
123 | Deploys a deployable to remote container. |
124 |
125 |
126 | cargoUndeployRemote |
127 | - |
128 | CargoUndeployRemote |
129 | Undeploys a deployable from remote container. |
130 |
131 |
132 | cargoRedeployRemote |
133 | - |
134 | CargoRedeployRemote |
135 | Redeploys a deployable to remote container. |
136 |
137 |
138 | cargoRunLocal |
139 | - |
140 | CargoRunLocal |
141 | Starts the local container, deploys a deployable and waits for the user to press CTRL + C to stop. |
142 |
143 |
144 | cargoStartLocal |
145 | - |
146 | CargoStartLocal |
147 | Starts the local container, deploys a deployable and then do other tasks (for example, execute tests). |
148 |
149 |
150 | cargoRedeployLocal |
151 | - |
152 | CargoRedeployLocal |
153 | Redeploys a deployable on local container. |
154 |
155 |
156 | cargoStopLocal |
157 | - |
158 | CargoStopLocal |
159 | Stops local container. |
160 |
161 |
162 | cargoConfigureLocal |
163 | - |
164 | CargoConfigureLocal |
165 | Configures the local container. |
166 |
167 |
168 |
169 | ## Project layout
170 |
171 | The Cargo plugin uses the same layout as the War plugin.
172 |
173 | ## Extension properties
174 |
175 | The Cargo plugin defines the following convention properties in the `cargo` closure:
176 |
177 | * `containerId`: The container ID you are targeting. Please see the [list of supported containers](https://codehaus-cargo.github.io/cargo/Home.html) on the Cargo website.
178 | * `port`: The TCP port the container responds on (defaults to 8080).
179 |
180 | Within `cargo` you can define optional properties for the 1..n deployment artifacts in a closure named `deployable`. Each
181 | deployment artifact would be specified in its own closure:
182 |
183 | * `file`: Any type that can be passed to [Project.files(Object...)](https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#files-java.lang.Object...-) and resolves to a single file or a directory including arbitrary artifacts, exploded WAR directories and dependency configurations to be deployed to container (defaults to project/module artifact - WAR or EAR file).
184 | * `context`: The URL context the container is handling your web application on (defaults to WAR/EAR name).
185 |
186 | Keep in mind that you do not have to define the `deployable` closure if you just want to deploy the artifact defined by your
187 | Gradle project/module.
188 |
189 | Within `cargo` you can define properties for remote containers in a closure named `remote`:
190 |
191 | * `protocol`: The protocol of the remote container (defaults to `http`).
192 | * `hostname`: The hostname of the remote container.
193 | * `username`: The username credential for the remote container (optional).
194 | * `password`: The password credential for the remote container (optional).
195 |
196 | Within `cargo` you can define properties for local containers in a closure named `local`:
197 |
198 | * `jvmArgs`: The JVM arguments for a local container.
199 | * `outputFile`: The log file of your local container (defaults to writing to the console).
200 | * `logFile`: The Cargo log file of your local container (defaults to writing to the console).
201 | * `logLevel`: The log level to run the container with (optional). The valid levels are `low`, `medium` and `high`.
202 | * `homeDir`: The home directory of your local container installation.
203 | * `configHomeDir`: The home directory of your local container's configuration.
204 | * `configFile`: The [configuration files](https://codehaus-cargo.github.io/cargo/Configuration+files+option.html) you want to add to your
205 | container's configuration. The `configFile` is a closure itself and requires you to provide the attributes `files` and `toDir`.
206 | A [`FileCollection`](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/FileCollection.html) should be used as `files` attribute and `toDir` should be a `String`.
207 | Multiple configuration file destinations can be defined by creating more than one `configFile` closure.
208 | * `rmiPort`: The port to use when communicating with this server, for example to start and stop it.
209 | * `startStopTimeout`: The timeout (in ms) in which to determine if the container is successfully started or stopped (defaults to 120000ms).
210 | * `extraClasspath`: A [`FileCollection`](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/FileCollection.html)
211 | that provides extra elements to the local [container classpath](http://cargo.codehaus.org/Container+Classpath) (optional).
212 | * `sharedClasspath`: A [`FileCollection`](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/FileCollection.html)
213 | that provides extra elements to the [application classpath](https://codehaus-cargo.github.io/cargo/Application+Classpath.html), and not to the
214 | local container (optional).
215 |
216 | ### Container properties
217 |
218 | Within `local` and `remote` you can define container-specific properties. These properties can be looked up on
219 | the Cargo homepage. The following example shows how to set the AJP port for a local Tomcat container:
220 |
221 | cargo {
222 | local {
223 | containerProperties {
224 | property 'cargo.tomcat.ajp.port', 9099
225 | }
226 | }
227 | }
228 |
229 | ### System properties
230 |
231 | Local containers can use system properties passed to it. The following example shows how to set a single system property named `myproperty`:
232 |
233 | cargo {
234 | local {
235 | systemProperties {
236 | property 'myproperty', 'myvalue'
237 | }
238 | }
239 | }
240 |
241 | ### Automatically bootstrapping a local container
242 |
243 | If you decide to use the [ZIP installer](https://codehaus-cargo.github.io/cargo/Installer.html) Cargo will automatically download your container. You can
244 | define its properties in the closure `installer`. The installer only applies to "local" Cargo tasks.
245 |
246 | * `installUrl`: The URL to download the container distribution from.
247 | * `downloadDir`: Target directory to download the container distribution to.
248 | * `extractDir`: Directory to extract the downloaded container distribution to.
249 |
250 | Please refer to the individual configuration properties on the Cargo homepage. All of these properties can be overridden
251 | by project properties. The name of the project properties is the same as in the Cargo manual.
252 |
253 | If you wish to benefit from Gradle dependency cache when resolving container distributions you can use a configuration instead of a url when configuring the installer:
254 |
255 | configurations {
256 | tomcat
257 | }
258 |
259 | dependencies {
260 | tomcat "org.apache.tomcat:tomcat:9.0.14@zip"
261 | }
262 |
263 | cargo {
264 | local {
265 | installer {
266 | installConfiguration = configurations.tomcat
267 | }
268 | }
269 | }
270 |
271 | ### Example
272 |
273 | cargo {
274 | containerId = 'tomcat6x'
275 | port = 9090
276 |
277 | deployable {
278 | context = 'myawesomewebapp'
279 | }
280 |
281 | remote {
282 | hostname = 'cloud.internal.it'
283 | username = 'superuser'
284 | password = 'secretpwd'
285 | }
286 |
287 | local {
288 | homeDir = file('/home/user/dev/tools/apache-tomcat-6.0.32')
289 | outputFile = file('build/output.log')
290 | startStopTimeout = 60000
291 |
292 | containerProperties {
293 | property 'cargo.tomcat.ajp.port', 9099
294 | }
295 | }
296 | }
297 |
298 | ## FAQ
299 |
300 | **I want to automatically assemble my project's artifact when executing a Cargo deployment task.**
301 |
302 | The task `cargoRunLocal` does not automatically depend on the `assemble` task. The reason behind that is that you might
303 | not want to deploy your project's artifact or your project does not generate a WAR or EAR file. Instead you might want
304 | to deploy one or more external artifacts. If your workflow looks like "compile the code", "generate the artifact" and "deploy"
305 | then you make a Cargo deployment task depends on the `assemble` task. Here's one example:
306 |
307 | cargoRunLocal.dependsOn assemble
308 |
309 | **I am working on a multi-project build. Can I apply the same Cargo configuration to all of my web projects?**
310 |
311 | Gradle allows for filtering subprojects by certain criteria. To inject the relevant configuration from the root project
312 | of your build, you will need to identify all subprojects that apply the War plugin (of course the same concept works
313 | for Ear projects). Use the `configure` method to apply the Cargo plugin and your configuration as shown in the following
314 | code snippet:
315 |
316 | def webProjects() {
317 | subprojects.findAll { subproject -> subproject.plugins.hasPlugin('war') }
318 | }
319 |
320 | gradle.projectsEvaluated {
321 | configure(webProjects()) {
322 | apply plugin: 'com.bmuschko.cargo'
323 |
324 | cargo {
325 | containerId = 'tomcat7x'
326 |
327 | remote {
328 | hostname = 'localhost'
329 | username = 'manager'
330 | password = 'manager'
331 | }
332 | }
333 | }
334 | }
335 |
336 | **I would like to deploy multiple artifacts to my container. How do I do that?**
337 |
338 | You would specify each artifact in a separate `deployable` closure. Each of the closures should assign a unique URL context.
339 | The following example demonstrates how a Cargo setup with three different artifacts deployed to a local Tomcat:
340 |
341 | cargo {
342 | containerId = 'tomcat6x'
343 | port = 9090
344 |
345 | deployable {
346 | file = file('/home/foo/bar/web-services.war')
347 | context = 'web-services'
348 | }
349 |
350 | deployable {
351 | file = file('/home/foo/bar/web-app.war')
352 | context = 'web-app'
353 | }
354 |
355 | deployable {
356 | file = file('/home/foo/bar/enterprise-app.ear')
357 | context = 'enterprise-app'
358 | }
359 |
360 | local {
361 | homeDir = file('/home/user/dev/tools/apache-tomcat-6.0.32')
362 | }
363 | }
364 |
365 | **Is there a way to let Cargo automatically install the container I'd like to use?**
366 |
367 | Cargo allows for defining a container that gets automatically downloaded and installed on your local disk. All you need to
368 | do is to specify the `installer` closure. The following code snippet downloads, installs and uses Tomcat 7:
369 |
370 | cargo {
371 | containerId = 'tomcat7x'
372 |
373 | local {
374 | installer {
375 | installUrl = 'http://apache.osuosl.org/tomcat/tomcat-7/v7.0.27/bin/apache-tomcat-7.0.27.zip'
376 | downloadDir = file("$buildDir/download")
377 | extractDir = file("$buildDir/extract")
378 | }
379 | }
380 | }
381 |
382 | **I'd like to add a configuration file to my local container. How do I do that?**
383 |
384 | For local containers a closure named `configFile` can be used that defines the source files and directory you would like
385 | to use the file from at runtime. If you need to copy files into more than one destinations just create multiple `configFile` closures.
386 |
387 | cargo {
388 | containerId = 'jboss5x'
389 |
390 | local {
391 | configFile {
392 | files = project.files('src/main/jboss5/login-config.xml')
393 | toDir = 'conf'
394 | }
395 |
396 | configFile {
397 | files = project.files('src/main/jboss5/login-config.xml', 'src/main/jboss5/sample-users.properties')
398 | toDir = 'conf/props'
399 | }
400 | }
401 | }
402 |
403 | To add binary file(s) you should use `file` closure(s) instead:
404 |
405 | cargo {
406 | containerId = 'glassfish3x'
407 |
408 | local {
409 | file {
410 | file = file('../config/db/mysql-connector-java-5.1.23-bin.jar')
411 | toDir = 'lib'
412 | }
413 | }
414 | }
415 |
416 | **I want to set up and configure my own Cargo task for more than one container. Can this be done?**
417 |
418 | Absolutely. The Cargo base plugin provides all tasks needed to set up deployment tasks. All you need to do is to create one
419 | or more tasks and configure the mandatory properties. The following example shows how to set up local container tasks
420 | for Tomcat and Jetty:
421 |
422 | apply plugin: 'com.bmuschko.cargo-base'
423 |
424 | task myTomcatRun(type: com.bmuschko.gradle.cargo.tasks.local.CargoRunLocal) {
425 | containerId = 'tomcat7x'
426 | homeDir = file('/home/user/dev/tools/apache-tomcat-7.0.42')
427 | }
428 |
429 | task myJettyRun(type: com.bmuschko.gradle.cargo.tasks.local.CargoRunLocal) {
430 | containerId = 'jetty9x'
431 | homeDir = file('/home/user/dev/tools/jetty-distribution-9.0.4.v20130625')
432 | }
433 |
434 | **I'd like to create deployment tasks for a rolling deployment to multiple remote containers. How do I do this?**
435 |
436 | Gradle allows for dynamically creating tasks based on your build script logic. The following example shows how to create
437 | three Tomcat deployment tasks and how to configure them with the help of a simple data structure. At the end of the script we
438 | also add another task that triggers the deployment to all remote containers.
439 |
440 | class RemoteContainer {
441 | String name
442 | String hostname
443 | Integer port
444 | String username
445 | String password
446 | }
447 |
448 | def remoteContainers = [new RemoteContainer(name: 'tomcat1', hostname: 'remote-tomcat1',
449 | port: 9090, username: 'admin', password: 's3cr3t'),
450 | new RemoteContainer(name: 'tomcat2', hostname: 'remote-tomcat2',
451 | port: 8050, username: 'deployer', password: 'qwerty'),
452 | new RemoteContainer(name: 'tomcat3', hostname: 'remote-tomcat3',
453 | port: 8888, username: 'su', password: 'powerful')]
454 |
455 | apply plugin: 'com.bmuschko.cargo-base'
456 |
457 | remoteContainers.each { config ->
458 | task "deployRemote${config.name.capitalize()}"(type: com.bmuschko.gradle.cargo.tasks.remote.CargoDeployRemote) {
459 | description = "Deploys WAR to remote Tomcat '${config.name}'."
460 | containerId = 'tomcat7x'
461 | hostname = config.hostname
462 | port = config.port
463 | username = config.username
464 | password = config.password
465 | }
466 | }
467 |
468 | task deployToAllRemoteTomcats {
469 | dependsOn remoteContainers.collect { "deployRemote${it.name.capitalize()}" }
470 | description = 'Deploys to all remote Tomcat containers.'
471 | group = 'deployment'
472 | }
473 |
474 | **Before a remote deployment I would like to restart my container. Can this be done?**
475 |
476 | Yes, this is possible with the help of the [Cargo daemon](https://codehaus-cargo.github.io/cargo/Cargo+Daemon.html) functionality. Please
477 | refer to the Cargo online documentation for setting up the Cargo daemon JVM process and configuring a container. With
478 | this plugin, you can use custom tasks to start and stop a container. The following example stops, starts and then redeploys
479 | an artifact.
480 |
481 | apply plugin: 'com.bmuschko.cargo'
482 |
483 | cargo {
484 | ...
485 | }
486 |
487 | ext.tomcat7HandleId = 'tomcat7'
488 |
489 | task cargoDaemonStop(type: com.bmuschko.gradle.cargo.tasks.daemon.CargoDaemonStop) {
490 | handleId = tomcat7HandleId
491 | }
492 |
493 | task cargoDaemonStart(type: com.bmuschko.gradle.cargo.tasks.daemon.CargoDaemonStart) {
494 | handleId = tomcat7HandleId
495 | }
496 |
497 | cargoDaemonStart.mustRunAfter cargoDaemonStop
498 | cargoRedeployRemote.dependsOn cargoDaemonStop, cargoDaemonStart
499 |
500 |
--------------------------------------------------------------------------------
/RELEASE_NOTES.md:
--------------------------------------------------------------------------------
1 | ### Version 2.9.0 (February 19, 2022)
2 |
3 | * Upgrade to Codehaus Cargo 1.9.10 - [Pull request 205](https://github.com/bmuschko/gradle-cargo-plugin/pull/205).
4 | *
5 | ### Version 2.8.0 (December 17, 2020)
6 |
7 | * Version upgrades for Codehaus Cargo and Java - [Pull request 204](https://github.com/bmuschko/gradle-cargo-plugin/pull/204).
8 |
9 | ### Version 2.7.1 (February 5, 2020)
10 |
11 | * Upgrade to Codehaus Cargo 1.7.10 - [Pull request 199](https://github.com/bmuschko/gradle-cargo-plugin/pull/199).
12 |
13 | ### Version 2.7.0 (December 14, 2019)
14 |
15 | * Add cargo-licensed-dtds to the dependencies and documentation - [Pull request 198](https://github.com/bmuschko/gradle-cargo-plugin/pull/198).
16 |
17 | ### Version 2.6.2 (December 12, 2019)
18 |
19 | * Upgrade to Cargo Ant tasks version 1.7.9 to ensure Gradle 6.0-compatibility - [Issue 196](https://github.com/bmuschko/gradle-cargo-plugin/issues/196).
20 |
21 | ### Version 2.6.1 (March 6, 2019)
22 |
23 | * Deployable should be declarable without a context - [Pull request 193](https://github.com/bmuschko/gradle-cargo-plugin/pull/193).
24 |
25 | ### Version 2.6 (February 10, 2019)
26 |
27 | * Allow use of use of locally installed container - [Pull request 191](https://github.com/bmuschko/gradle-cargo-plugin/pull/191).
28 | * **Breaking Change!** Rename timeout parameter to ensure compatibility with Gradle's built-in timeout - [Pull request 188](https://github.com/bmuschko/gradle-cargo-plugin/pull/188).
29 |
30 | ### Version 2.5 (January 29, 2018)
31 |
32 | * Support using a configuration as a source of the container for ZIP installer - [Pull request 176](https://github.com/bmuschko/gradle-cargo-plugin/pull/176).
33 | * Allow using outputs and configurations as deployables - [Pull request 178](https://github.com/bmuschko/gradle-cargo-plugin/pull/178).
34 | * **Breaking Change!** Support using task outputs and configurations as config files - [Pull request 180](https://github.com/bmuschko/gradle-cargo-plugin/pull/180).
35 |
36 | ### Version 2.4 (July 29, 2018)
37 |
38 | * Allow setting timeout to 0 - [Pull request 169](https://github.com/bmuschko/gradle-cargo-plugin/pull/169).
39 | * Upgrade to Cargo Ant tasks version 1.6.8.
40 | * Upgrade to Gradle Wrapper 4.9.
41 |
42 | ### Version 2.3 (January 2, 2018)
43 |
44 | * Introduce task for configuring local container - [Pull request 144](https://github.com/bmuschko/gradle-cargo-plugin/pull/144).
45 | * Upgrade to Cargo Ant tasks version 1.6.6.
46 | * Upgrade to Gradle Wrapper 4.4.1.
47 |
48 | ### Version 2.2.3 (June 4, 2016)
49 |
50 | * Remove use of Gradle internal methods.
51 | * Upgrade to Gradle Wrapper 2.13.
52 |
53 | ### Version 2.2.2 (December 4, 2015)
54 |
55 | * Expose properties for configuring a local embedded container - [Pull request 141](https://github.com/bmuschko/gradle-cargo-plugin/pull/141).
56 |
57 | ### Version 2.2.1 (September 6, 2015)
58 |
59 | * Fix typo in task description - [Pull request 135](https://github.com/bmuschko/gradle-cargo-plugin/pull/135).
60 | * Fixed configFile and file destination dir specification - [Pull request 121](https://github.com/bmuschko/gradle-cargo-plugin/pull/121).
61 | * Align `logFile` extension property with task property name - [Issue 110](https://github.com/bmuschko/gradle-cargo-plugin/issues/110).
62 | * Removed "magic" project properties.
63 |
64 | ### Version 2.2 (August 31, 2015)
65 |
66 | * Upgrade to Gradle Wrapper 2.6.
67 | * Removed container ID validation - [Issue 134](https://github.com/bmuschko/gradle-cargo-plugin/issues/134).
68 | * Cargo home directory is not an `@Input`, hashing can run into problems with locked files - [Pull request 133](https://github.com/bmuschko/gradle-cargo-plugin/pull/133).
69 |
70 | ### Version 2.1.1 (May 16, 2015)
71 |
72 | * Upgrade to Gradle Wrapper 2.4.
73 | * Introduced redeploy task for local containers - [Pull request 126](https://github.com/bmuschko/gradle-cargo-plugin/pull/126).
74 |
75 | ### Version 2.1 (March 30, 2015)
76 |
77 | * Upgrade to Cargo Ant tasks version 1.4.13.
78 | * Support for exploded WAR deployment - [Issue 115](https://github.com/bmuschko/gradle-cargo-plugin/issues/115).
79 |
80 | ### Version 2.0.3 (December 7, 2014)
81 |
82 | * Set Java target compatibility back to 1.6 - [Pull request 113](https://github.com/bmuschko/gradle-cargo-plugin/pull/113).
83 |
84 | ### Version 2.0.2 (November 15, 2014)
85 |
86 | * Directory for property `configHomeDir` is created automatically if it doesn't exist - [Issue 101](https://github.com/bmuschko/gradle-cargo-plugin/issues/101).
87 | * Upgrade to Cargo version 1.4.10.
88 | * Don't use `AntClassLoader` as parent classloader for daemon tasks.
89 |
90 | ### Version 2.0.1 (October 13, 2014)
91 |
92 | * Fix implementation class of Cargo plugin identifier - [Issue 107](https://github.com/bmuschko/gradle-cargo-plugin/issues/107).
93 |
94 | ### Version 2.0 (October 11, 2014)
95 |
96 | * Upgrade to Gradle Wrapper 2.1.
97 | * Changed package name to `com.bmuschko.gradle.vagrant`.
98 | * Changed group ID to `com.bmuschko`.
99 | * Adapted plugin IDs to be compatible with Gradle's plugin portal.
100 |
101 | ### Version 1.5.2 (October 11, 2014)
102 |
103 | * Deployment task should never be up-to-date - [Issue 103](https://github.com/bmuschko/gradle-cargo-plugin/issues/103).
104 | * Support for JBoss74x (aka EAP 6.3.x) container - [Pull request 105](https://github.com/bmuschko/gradle-cargo-plugin/pull/105).
105 |
106 | ### Version 1.5.1 (August 29, 2014)
107 |
108 | * Provide `equals`/`hashCode` for POJO input properties [Issue 97](https://github.com/bmuschko/gradle-cargo-plugin/issues/97).
109 |
110 | ### Version 1.5 (April 2, 2014)
111 |
112 | * Support for starting and stopping containers with the help of Cargo daemon.
113 |
114 | ### Version 1.4.1 (March 22, 2014)
115 |
116 | * `cargoStartLocal` and `cargoRunLocal` fail if log file doesn't exist - [Issue 83](https://github.com/bmuschko/gradle-cargo-plugin/issues/83).
117 | * Renamed property `output` to `outputFile`.
118 | * Some of the input properties needed to be `Serializable`.
119 |
120 | ### Version 1.4 (February 15, 2014)
121 |
122 | * Added sharedClasspath and extraClasspath support for local containers - [Pull request 73](https://github.com/bmuschko/gradle-cargo-plugin/pull/77).
123 |
124 | ### Version 1.3 (January 25, 2014)
125 |
126 | * Broke out base plugin to allow full control for creating and configuring deployment tasks.
127 | * The Cargo libraries now get pre-configured. A custom Cargo version can still be assigned via the configuration `cargo`.
128 |
129 | ### Version 1.2.2 (January 06, 2013)
130 |
131 | * Fix input annotation for `configHomeDir` property - [Pull request 73](https://github.com/bmuschko/gradle-cargo-plugin/pull/73).
132 |
133 | ### Version 1.2.1 (December 28, 2013)
134 |
135 | * Fixed missing property `UNDEPLOY_ACTION` on remote task - [Issue 72](https://github.com/bmuschko/gradle-cargo-plugin/issues/72).
136 |
137 | ### Version 1.2 (December 24, 2013)
138 |
139 | * Create custom task types for each action - [Issue 20](https://github.com/bmuschko/gradle-cargo-plugin/issues/20).
140 |
141 | ### Version 1.1 (December 16, 2013)
142 |
143 | * Adding support of the cargo timeout property - [Pull request 66](https://github.com/bmuschko/gradle-cargo-plugin/pull/66).
144 | * Harden validation code for deployables - [Issue 67](https://github.com/bmuschko/gradle-cargo-plugin/issues/67).
145 | * Add support for passing system properties to container - [Issue 68](https://github.com/bmuschko/gradle-cargo-plugin/issues/68).
146 |
147 | ### Version 1.0 (December 15, 2013)
148 |
149 | * Allow configuring container using generic properties.
150 | * Update of supported containers.
151 | * Upgrade to Gradle Wrapper 1.9.
152 |
153 | ### Version 0.6.1 (July 21, 2013)
154 |
155 | * Support for Jetty 9.x - [Pull request 48](https://github.com/bmuschko/gradle-cargo-plugin/pull/48).
156 | * Fix deprecation warnings in gradle 1.6 - [Pull request 48](https://github.com/bmuschko/gradle-cargo-plugin/pull/42).
157 | * Adding support for specifying configuration home - [Pull request 40](https://github.com/bmuschko/gradle-cargo-plugin/pull/40).
158 |
159 | ### Version 0.6 (April 16, 2013)
160 |
161 | * Avoid having to assign the WAR file for a remote undeploy action - [Issue 30](https://github.com/bmuschko/gradle-cargo-plugin/issues/30).
162 | * _Note:_ This release requires you to use Cargo >= 1.3.3.
163 |
164 | ### Version 0.5.9 (March 8, 2013)
165 |
166 | * Added configuration option for binary files - [Pull request 33](https://github.com/bmuschko/gradle-cargo-plugin/pull/32).
167 |
168 | ### Version 0.5.8 (February 25, 2013)
169 |
170 | * Capturing Cargo Ant logging - [Pull request 33](https://github.com/bmuschko/gradle-cargo-plugin/pull/33).
171 | * Upgrade to Gradle Wrapper 1.4.
172 |
173 | ### Version 0.5.7 (January 13, 2013)
174 |
175 | * Avoid masking exceptions thrown in build.gradle - [Issue 29](https://github.com/bmuschko/gradle-cargo-plugin/issues/29).
176 | * Some of the container-specific task property classes did not implement TaskProperty - [Issue 27](https://github.com/bmuschko/gradle-cargo-plugin/issues/27).
177 |
178 | ### Version 0.5.6 (October 14, 2012)
179 |
180 | * Expose convention property for setting the RMI port - [Issue 21](https://github.com/bmuschko/gradle-cargo-plugin/issues/21).
181 |
182 | ### Version 0.5.5 (August 4, 2012)
183 |
184 | * Provides support for configuration files - [Issue 14](https://github.com/bmuschko/gradle-cargo-plugin/issues/14).
185 |
186 | ### Version 0.5.4 (July 8, 2012)
187 |
188 | * The ZIP URL installer convention property wasn't set correctly for the default local container implementation.
189 | * Checking if all properties are set for the ZIP URL installer closure before applying it.
190 | * Refactored duplicated code for setting the convention properties of a local container.
191 |
192 | ### Version 0.5.3 (July 7, 2012)
193 |
194 | * Support for ZIP artifact installer - [Issue 15](https://github.com/bmuschko/gradle-cargo-plugin/issues/15).
195 | * Upgrade to Gradle Wrapper 1.0.
196 | * Use Groovy @Slf4j annotation for logging.
197 |
198 | ### Version 0.5.2 (December 5, 2011)
199 |
200 | * Fixed minor bug in documentation and code about setting local container-specific properties.
201 |
202 | ### Version 0.5.1 (December 3, 2011)
203 |
204 | * Provide convention properties for Cargo and container log files.
205 |
206 | ### Version 0.5 (November 27, 2011)
207 |
208 | * Allow deployment of multiple artifacts - [Issue 9](https://github.com/bmuschko/gradle-cargo-plugin/issues/9). _Note:_ This slightly
209 | changes the structure of the convention properties. Please check the documentation!
210 |
211 | ### Version 0.4 (November 27, 2011)
212 |
213 | * Support for JVM arguments in local containers.
214 | * Support for configuration properties specific to local container product.
215 | * The deployable artifact can either be a WAR or an EAR file. _Note:_ This release requires your project to run with Gradle >= [1.0-m4](http://wiki.gradle.org/display/GRADLE/Gradle+1.0-milestone-4+Release+Notes).
216 | * Upgrade to Gradle Wrapper 1.0-m6.
217 |
218 | ### Version 0.3 (June 26, 2011)
219 |
220 | * Exposed local run task introduced in Cargo 1.1.1. The plugin does not favor the [deprecation](http://cargo.codehaus.org/Ant+support)
221 | of the `wait` convention property. It got removed completely. Please use `cargoRunLocal` or `cargoStartLocal` depending on
222 | your use case.
223 | * _Note:_ This release requires you to use Cargo >= 1.1.1.
224 |
225 | ### Version 0.2 (May 30, 2011)
226 |
227 | * Added property for setting `cargo.protocol` to remote container tasks.
228 |
229 | ### Version 0.1 (May 27, 2011)
230 |
231 | * Initial release.
232 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'groovy'
3 | id 'maven-publish'
4 | id 'java-gradle-plugin'
5 | id 'com.gradle.plugin-publish' version '0.20.0'
6 | id 'org.ajoberstar.git-publish' version '2.1.3'
7 | }
8 |
9 | apply from: "$rootProject.projectDir/gradle/integration-test.gradle"
10 |
11 | def compatibilityVersion = JavaVersion.VERSION_1_8
12 | sourceCompatibility = compatibilityVersion
13 | targetCompatibility = compatibilityVersion
14 | group = 'com.bmuschko'
15 | version = '2.9.0'
16 |
17 | repositories {
18 | mavenCentral()
19 | }
20 |
21 | dependencies {
22 | def cargoVersion = '1.9.10'
23 | implementation "org.codehaus.cargo:cargo-daemon-client:$cargoVersion"
24 | testImplementation('org.spockframework:spock-core:1.3-groovy-2.4') {
25 | exclude group: 'org.codehaus.groovy'
26 | }
27 | testImplementation "org.codehaus.cargo:cargo-ant:$cargoVersion"
28 | }
29 |
30 | task sourcesJar(type: Jar) {
31 | archiveClassifier = 'sources'
32 | from sourceSets.main.allSource
33 | }
34 |
35 | task groovydocJar(type: Jar) {
36 | dependsOn groovydoc
37 | archiveClassifier = 'groovydoc'
38 | from groovydoc.destinationDir
39 | }
40 |
41 | task javadocJar(type: Jar) {
42 | dependsOn javadoc
43 | archiveClassifier = 'javadoc'
44 | from javadoc.destinationDir
45 | }
46 |
47 | artifacts {
48 | archives sourcesJar
49 | archives groovydocJar
50 | archives javadocJar
51 | }
52 |
53 | gradlePlugin {
54 | plugins {
55 | cargoBasePlugin {
56 | id = 'com.bmuschko.cargo-base'
57 | implementationClass = 'com.bmuschko.gradle.cargo.CargoBasePlugin'
58 | }
59 | cargoPlugin {
60 | id = 'com.bmuschko.cargo'
61 | implementationClass = 'com.bmuschko.gradle.cargo.CargoPlugin'
62 | }
63 | }
64 | }
65 |
66 | pluginBundle {
67 | website = "https://github.com/bmuschko/gradle-cargo-plugin"
68 | vcsUrl = "https://github.com/bmuschko/gradle-cargo-plugin"
69 | tags = ['deployment', 'container', 'web', 'ear', 'cargo']
70 |
71 | mavenCoordinates {
72 | groupId = project.group.toString()
73 | artifactId = project.name
74 | version = project.version.toString()
75 | }
76 |
77 | plugins {
78 | cargoBasePlugin {
79 | displayName = 'Gradle Cargo Base Plugin'
80 | description = 'Plugin that provides Cargo custom task types, pre-configures classpath and deployables.'
81 | }
82 | cargoPlugin {
83 | displayName = 'Gradle Cargo Plugin'
84 | description = 'Plugin that provides a set of local and remote Cargo tasks and exposes extension for configuration.'
85 | }
86 | }
87 | }
88 |
89 | gitPublish {
90 | repoUri = 'git@github.com:bmuschko/gradle-cargo-plugin.git'
91 | branch = 'gh-pages'
92 |
93 | contents {
94 | from(javadoc.outputs.files) {
95 | into 'docs/javadoc'
96 | }
97 | from(groovydoc.outputs.files) {
98 | into 'docs/groovydoc'
99 | }
100 | }
101 | }
102 |
103 | gitPublishCopy.dependsOn javadoc, groovydoc
--------------------------------------------------------------------------------
/gradle/integration-test.gradle:
--------------------------------------------------------------------------------
1 | sourceSets {
2 | integrationTest {
3 | groovy.srcDir file('src/integTest/groovy')
4 | resources.srcDir file('src/integTest/resources')
5 | compileClasspath += sourceSets.main.output + configurations.testRuntimeClasspath
6 | runtimeClasspath += output + compileClasspath
7 | }
8 | }
9 |
10 | task integrationTest(type: Test) {
11 | description = 'Runs the integration tests.'
12 | group = 'verification'
13 | testClassesDirs = sourceSets.integrationTest.output.classesDirs
14 | classpath = sourceSets.integrationTest.runtimeClasspath
15 | mustRunAfter test
16 | }
17 |
18 | check.dependsOn integrationTest
19 |
20 | dependencies {
21 | integrationTestImplementation "io.github.http-builder-ng:http-builder-ng-core:1.0.3"
22 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmuschko/gradle-cargo-plugin/12940deb48fa93e033a922db96ed3f5eb7956ad5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'gradle-cargo-plugin'
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/AbstractIntegrationSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import groovyx.net.http.HttpBuilder
4 | import org.gradle.testkit.runner.BuildResult
5 | import org.gradle.testkit.runner.GradleRunner
6 | import org.junit.Rule
7 | import org.junit.rules.TemporaryFolder
8 | import spock.lang.Specification
9 |
10 | abstract class AbstractIntegrationSpec extends Specification {
11 |
12 | protected final static String WAR_CONTEXT = 'test-servlet'
13 |
14 | @Rule
15 | TemporaryFolder testProjectDir
16 |
17 | File buildScript
18 |
19 | void setup() {
20 | buildScript = testProjectDir.newFile('build.gradle') << """
21 | plugins {
22 | id 'com.bmuschko.cargo'
23 | }
24 | """
25 | }
26 |
27 | void configureCargoInstaller() {
28 | buildScript << """
29 | configurations {
30 | tomcat
31 | }
32 |
33 | dependencies {
34 | tomcat "org.apache.tomcat:tomcat:9.0.14@zip"
35 | }
36 |
37 | cargo {
38 | containerId = "tomcat9x"
39 |
40 | local {
41 | installer {
42 | installConfiguration = configurations.tomcat
43 | downloadDir = file("\$buildDir/download")
44 | extractDir = file("\$buildDir/extract")
45 | }
46 | }
47 | }
48 | """
49 | }
50 |
51 | BuildResult runBuild(String... arguments) {
52 | GradleRunner.create()
53 | .withProjectDir(testProjectDir.root)
54 | .withArguments("-s", *arguments)
55 | .withPluginClasspath()
56 | .forwardOutput()
57 | .build()
58 | }
59 |
60 | String requestServletResponseText() {
61 | HttpBuilder.configure {
62 | request.uri = "http://localhost:8080/$WAR_CONTEXT"
63 | }.get()
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/ConfigFileIntegrationSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.util.fixture.TextResourceFactoryJarFixture
4 | import com.bmuschko.gradle.cargo.util.fixture.TextResourceLoaderServletWarFixture
5 | import groovyx.net.http.HttpBuilder
6 |
7 | class ConfigFileIntegrationSpec extends AbstractIntegrationSpec {
8 |
9 | private final String TEXT_RESOURCE_NAME = "test/resource"
10 | private final String TEXT_RESOURCE_VALUE = "test resource value"
11 |
12 | void setup() {
13 | def textResourceFactoryJarFixture = new TextResourceFactoryJarFixture(testProjectDir.root, ":textResourceFactory")
14 | def textResourceLoaderServletWarFixture = new TextResourceLoaderServletWarFixture(testProjectDir.root, ":textResourceLoader")
15 |
16 | configureCargoInstaller()
17 |
18 | buildScript << """
19 | import groovy.xml.MarkupBuilder
20 |
21 | repositories {
22 | mavenCentral()
23 | }
24 |
25 | configurations {
26 | war
27 | extraClasspath
28 | }
29 |
30 | dependencies {
31 | war project(path: '${textResourceLoaderServletWarFixture.projectPath}', configuration: 'archives')
32 | extraClasspath project('$textResourceFactoryJarFixture.projectPath')
33 | }
34 |
35 | cargo {
36 | local {
37 | extraClasspath = configurations.extraClasspath
38 | }
39 |
40 | deployable {
41 | file = configurations.war
42 | context = '$WAR_CONTEXT'
43 | }
44 | }
45 |
46 | task writeContextXml {
47 | def contextXml = new File(buildDir, "context.xml")
48 |
49 | outputs.file(contextXml)
50 |
51 | doLast {
52 | contextXml.withWriter { writer ->
53 | new MarkupBuilder(writer).Context {
54 | Resource(
55 | name: "$TEXT_RESOURCE_NAME",
56 | factory: "TextResourceFactory",
57 | value: "$TEXT_RESOURCE_VALUE"
58 | )
59 | }
60 | }
61 | }
62 | }
63 | """
64 | }
65 |
66 | void cleanup() {
67 | runBuild "cargoStopLocal"
68 | }
69 |
70 | void "can use a file collection as a config files source"() {
71 | given:
72 | buildScript << """
73 | cargo {
74 | local {
75 | configFile {
76 | files = writeContextXml.outputs.files
77 | toDir = "conf"
78 | }
79 | }
80 | }
81 | """
82 |
83 | when:
84 | runBuild "cargoStartLocal"
85 |
86 | then:
87 | requestTextResourceValue(TEXT_RESOURCE_NAME) == TEXT_RESOURCE_VALUE
88 | }
89 |
90 | String requestTextResourceValue(String resourceName) {
91 | HttpBuilder.configure {
92 | request.uri = "http://localhost:8080/$WAR_CONTEXT"
93 | request.uri.query = [resourceName: resourceName]
94 | }.get()
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/DefaultDeployableSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.util.fixture.HelloWorldServletWarFixture
4 |
5 | class DefaultDeployableSpec extends AbstractIntegrationSpec {
6 |
7 | HelloWorldServletWarFixture servletWarFixture
8 |
9 | void setup() {
10 | servletWarFixture = new HelloWorldServletWarFixture(testProjectDir.root, ":")
11 | configureCargoInstaller()
12 | }
13 |
14 | void cleanup() {
15 | runBuild "cargoStopLocal"
16 | }
17 |
18 | def "project artifact is configured as a deployable including task dependencies"() {
19 | given:
20 | buildScript << """
21 | cargo {
22 | deployable {
23 | context = '$WAR_CONTEXT'
24 | }
25 | }
26 | """
27 |
28 | when:
29 | runBuild "cargoStartLocal"
30 |
31 | then:
32 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/DeployableIntegrationSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.util.fixture.HelloWorldServletWarFixture
4 |
5 | class DeployableIntegrationSpec extends AbstractIntegrationSpec {
6 |
7 | HelloWorldServletWarFixture servletWarFixture
8 |
9 | void setup() {
10 | servletWarFixture = new HelloWorldServletWarFixture(testProjectDir.root, ":$WAR_CONTEXT")
11 | configureCargoInstaller()
12 | buildScript << """
13 | import com.bmuschko.gradle.cargo.tasks.local.LocalCargoContainerTask
14 |
15 | repositories {
16 | mavenCentral()
17 | }
18 |
19 | configurations {
20 | war
21 | }
22 |
23 | dependencies {
24 | war project(path: '${servletWarFixture.projectPath}', configuration: 'archives')
25 | }
26 | """
27 | }
28 |
29 | void cleanup() {
30 | runBuild "cargoStopLocal"
31 | }
32 |
33 | def "can use a file as a deployable"() {
34 | given:
35 | buildScript << """
36 | task configureCargoDeployable {
37 | inputs.files(configurations.war)
38 |
39 | doLast {
40 | cargo {
41 | deployable {
42 | file = configurations.war.singleFile
43 | context = '$WAR_CONTEXT'
44 | }
45 | }
46 | }
47 | }
48 |
49 | tasks.withType(LocalCargoContainerTask) {
50 | dependsOn configureCargoDeployable
51 | }
52 | """
53 |
54 | when:
55 | runBuild "cargoStartLocal"
56 |
57 | then:
58 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
59 | }
60 |
61 | def "can use a file collection as a deployable"() {
62 | given:
63 | buildScript << """
64 | cargo {
65 | deployable {
66 | file = configurations.war
67 | context = '$WAR_CONTEXT'
68 | }
69 | }
70 | """
71 |
72 | when:
73 | runBuild "cargoStartLocal"
74 |
75 | then:
76 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
77 | }
78 |
79 | def "can deploy without context parameter"() {
80 | given:
81 | buildScript << """
82 | cargo {
83 | deployable {
84 | file = configurations.war
85 | }
86 | }
87 | """
88 |
89 | when:
90 | runBuild "cargoStartLocal"
91 |
92 | then:
93 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/InstallerUrlIntegrationSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.util.fixture.HelloWorldServletWarFixture
4 |
5 | class InstallerUrlIntegrationSpec extends AbstractIntegrationSpec {
6 |
7 | HelloWorldServletWarFixture servletWarFixture
8 |
9 | void setup() {
10 | servletWarFixture = new HelloWorldServletWarFixture(testProjectDir.root, ":$WAR_CONTEXT")
11 | buildScript << """
12 | import com.bmuschko.gradle.cargo.tasks.local.LocalCargoContainerTask
13 |
14 | repositories {
15 | mavenCentral()
16 | }
17 |
18 | configurations {
19 | war
20 | }
21 |
22 | dependencies {
23 | war project(path: '${servletWarFixture.projectPath}', configuration: 'archives')
24 | }
25 |
26 | cargo {
27 | containerId = "tomcat9x"
28 |
29 | local {
30 | installer {
31 | downloadDir = file("\$buildDir/download")
32 | extractDir = file("\$buildDir/extract")
33 | }
34 | }
35 | }
36 |
37 | cargo {
38 | deployable {
39 | file = configurations.war
40 | context = '$WAR_CONTEXT'
41 | }
42 | }
43 | """
44 | }
45 |
46 | void cleanup() {
47 | runBuild "cargoStopLocal"
48 | }
49 |
50 | void "url can be used to configure installer source"() {
51 | given:
52 | buildScript << """
53 | cargo {
54 | local {
55 | installer {
56 | installUrl = "https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/9.0.14/tomcat-9.0.14.zip"
57 | }
58 | }
59 | }
60 | """
61 | when:
62 | runBuild "cargoStartLocal"
63 |
64 | then:
65 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
66 | }
67 |
68 | void "configuration can be used to configure installer source"() {
69 | given:
70 | buildScript << """
71 | configurations {
72 | tomcat
73 | }
74 |
75 | dependencies {
76 | tomcat "org.apache.tomcat:tomcat:9.0.14@zip"
77 | }
78 |
79 | cargo {
80 | local {
81 | installer {
82 | installConfiguration = configurations.tomcat
83 | }
84 | }
85 | }
86 | """
87 | when:
88 | runBuild "cargoStartLocal"
89 |
90 | then:
91 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/LocallyInstalledContainerIntegrationSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.util.fixture.HelloWorldServletWarFixture
4 |
5 | class LocallyInstalledContainerIntegrationSpec extends AbstractIntegrationSpec{
6 |
7 | HelloWorldServletWarFixture servletWarFixture
8 |
9 | def setup() {
10 | servletWarFixture = new HelloWorldServletWarFixture(testProjectDir.root, ":$WAR_CONTEXT")
11 | }
12 |
13 | void cleanup() {
14 | runBuild "cargoStopLocal"
15 | }
16 |
17 | def "can use a locally installed container"() {
18 | buildScript << """
19 | repositories {
20 | mavenCentral()
21 | }
22 |
23 | configurations {
24 | tomcat
25 | war
26 | }
27 |
28 | dependencies {
29 | tomcat "org.apache.tomcat:tomcat:9.0.14@zip"
30 | war project(path: '${servletWarFixture.projectPath}', configuration: 'archives')
31 | }
32 |
33 | task installTomcat(type: Copy) {
34 | from { zipTree(configurations.tomcat.singleFile) }
35 | into "\$buildDir/tomcat-home"
36 | eachFile { FileCopyDetails fileCopyDetails ->
37 | def original = fileCopyDetails.relativePath
38 | //strip the top level directory
39 | fileCopyDetails.relativePath = new RelativePath(original.file, *original.segments[1..-1])
40 | }
41 | }
42 |
43 | cargo {
44 | containerId = "tomcat9x"
45 |
46 | deployable {
47 | file = configurations.war
48 | context = '$WAR_CONTEXT'
49 | }
50 |
51 | local {
52 | homeDir = installTomcat.outputs.files.singleFile
53 | }
54 | }
55 |
56 | cargoStartLocal.dependsOn installTomcat
57 | """
58 |
59 | when:
60 | runBuild "cargoStartLocal"
61 |
62 | then:
63 | requestServletResponseText() == HelloWorldServletWarFixture.RESPONSE_TEXT
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/fixture/AbstractWarFixture.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util.fixture
2 |
3 | import groovy.transform.InheritConstructors
4 |
5 | @InheritConstructors
6 | abstract class AbstractWarFixture extends ProjectFixture {
7 |
8 | private final static String WEB_XML_FILENAME = 'web.xml'
9 |
10 | abstract String getServletClassName()
11 | abstract String getServletClassSource()
12 |
13 | protected void configure() {
14 | super.configure()
15 | writeWebXml()
16 | writeBuild()
17 | writeSources()
18 | }
19 |
20 | protected void writeWebXml() {
21 | new File(projectDir, WEB_XML_FILENAME) << """\
22 | |
23 | |
24 | |
25 | | $servletClassName
26 | | $servletClassName
27 | |
28 | |
29 | | $servletClassName
30 | | /
31 | |
32 | |
33 | """.stripMargin()
34 | }
35 |
36 | protected void writeBuild() {
37 | new File(projectDir, "build.gradle") << """
38 | apply plugin: 'war'
39 |
40 | repositories {
41 | mavenCentral()
42 | }
43 |
44 | dependencies {
45 | providedCompile "javax.servlet:javax.servlet-api:4.0.1"
46 | }
47 |
48 | war {
49 | webXml = file("$WEB_XML_FILENAME")
50 | }
51 | """
52 | }
53 |
54 | protected void writeSources() {
55 | def sourcesDirectory = new File(projectDir, 'src/main/java')
56 | sourcesDirectory.mkdirs()
57 |
58 | new File(sourcesDirectory, "${servletClassName}.java") << servletClassSource
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/fixture/HelloWorldServletWarFixture.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util.fixture
2 |
3 | import groovy.transform.InheritConstructors
4 |
5 | @InheritConstructors
6 | class HelloWorldServletWarFixture extends AbstractWarFixture {
7 |
8 | public final static String RESPONSE_TEXT = 'Hello World!'
9 |
10 | String getServletClassName() {
11 | "HelloWorld"
12 | }
13 |
14 | String getServletClassSource() {
15 | """
16 | import javax.servlet.http.HttpServlet;
17 | import javax.servlet.http.HttpServletRequest;
18 | import javax.servlet.http.HttpServletResponse;
19 | import java.io.IOException;
20 |
21 | public class $servletClassName extends HttpServlet {
22 | @Override
23 | protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
24 | response.setContentType("text/plain");
25 | response.getWriter().print("$RESPONSE_TEXT");
26 | }
27 | }
28 | """
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/fixture/ProjectFixture.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util.fixture
2 |
3 | class ProjectFixture {
4 |
5 | protected final File rootProjectDir
6 | protected final List projectPathSegments
7 |
8 | ProjectFixture(File rootProjectDir, String projectPath) {
9 | this.rootProjectDir = rootProjectDir
10 | this.projectPathSegments = projectPath.tokenize(":").findAll()
11 | configure()
12 | }
13 |
14 | protected void configure() {
15 | addProjectToSettings()
16 | projectDir.mkdirs()
17 | }
18 |
19 | protected void addProjectToSettings() {
20 | new File(rootProjectDir, "settings.gradle") << """
21 | include '$projectPath'
22 | """
23 | }
24 |
25 | protected File getProjectDir() {
26 | projectPathSegments ? new File(rootProjectDir, projectPathSegments.join('/')) : rootProjectDir
27 | }
28 |
29 | String getProjectPath() {
30 | ":${projectPathSegments.join(":")}"
31 | }
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/fixture/TextResourceFactoryJarFixture.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util.fixture
2 |
3 | import groovy.transform.InheritConstructors
4 |
5 | @InheritConstructors
6 | class TextResourceFactoryJarFixture extends ProjectFixture {
7 |
8 | private static final String CLASS_NAME = "TextResourceFactory"
9 |
10 | protected void configure() {
11 | super.configure()
12 | writeBuild()
13 | writeSources()
14 | }
15 |
16 | private void writeBuild() {
17 | new File(projectDir, "build.gradle") << """
18 | apply plugin: 'java'
19 | """
20 | }
21 |
22 | private void writeSources() {
23 | def sourcesDirectory = new File(projectDir, 'src/main/java')
24 | sourcesDirectory.mkdirs()
25 |
26 | new File(sourcesDirectory, "${CLASS_NAME}.java") << """
27 | import javax.naming.Context;
28 | import javax.naming.Name;
29 | import javax.naming.Reference;
30 | import javax.naming.spi.ObjectFactory;
31 | import java.util.Hashtable;
32 |
33 | public class $CLASS_NAME implements ObjectFactory {
34 | @Override
35 | public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable, ?> environment) {
36 | Reference reference = (Reference) obj;
37 | return reference.get("value").getContent().toString();
38 | }
39 | }
40 | """
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/integrationTest/groovy/com/bmuschko/gradle/cargo/util/fixture/TextResourceLoaderServletWarFixture.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util.fixture
2 |
3 | import groovy.transform.InheritConstructors
4 |
5 | @InheritConstructors
6 | class TextResourceLoaderServletWarFixture extends AbstractWarFixture {
7 |
8 | String getServletClassName() {
9 | "TextResourceLoader"
10 | }
11 |
12 | String getServletClassSource() {
13 | """
14 | import javax.naming.Context;
15 | import javax.naming.InitialContext;
16 | import javax.naming.NamingException;
17 | import javax.servlet.http.HttpServlet;
18 | import javax.servlet.http.HttpServletRequest;
19 | import javax.servlet.http.HttpServletResponse;
20 | import java.io.IOException;
21 |
22 | public class $servletClassName extends HttpServlet {
23 |
24 | @Override
25 | protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
26 | String resourceName = request.getParameter("resourceName");
27 |
28 | response.setContentType("text/plain");
29 | response.getWriter().print(lookupTextResource(resourceName));
30 | }
31 |
32 | private String lookupTextResource(String name) {
33 | try {
34 | Context context = (Context) new InitialContext().lookup("java:comp/env");
35 | return (String) context.lookup(name);
36 | } catch (NamingException e) {
37 | throw new RuntimeException(e);
38 | }
39 | }
40 | }
41 | """
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/CargoBasePlugin.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo
17 |
18 | import com.bmuschko.gradle.cargo.convention.Deployable
19 | import com.bmuschko.gradle.cargo.tasks.AbstractCargoContainerTask
20 | import com.bmuschko.gradle.cargo.tasks.daemon.CargoDaemon
21 | import com.bmuschko.gradle.cargo.util.ProjectInfoHelper
22 | import org.gradle.api.Plugin
23 | import org.gradle.api.Project
24 | import org.gradle.api.Task
25 |
26 | /**
27 | * A {@link org.gradle.api.Plugin} that provides custom task types for deploying WAR/EAR files to local and remote web containers.
28 | * The plugin pre-configures the dependencies on the external Cargo libraries. You will still need to define at least
29 | * one repository that the plugin can use to look for the libraries.
30 | */
31 | class CargoBasePlugin implements Plugin {
32 | static final String CONFIGURATION_NAME = 'cargo'
33 | static final String DAEMON_CONFIGURATION_NAME = 'cargoDaemon'
34 | static final String CARGO_DEFAULT_VERSION = '1.9.10'
35 |
36 | @Override
37 | void apply(Project project) {
38 | project.configurations.create(CONFIGURATION_NAME)
39 | .setVisible(false)
40 | .setTransitive(true)
41 | .setDescription('The Cargo Ant libraries to be used for this project.')
42 |
43 | project.configurations.create(DAEMON_CONFIGURATION_NAME)
44 | .setVisible(false)
45 | .setTransitive(true)
46 | .setDescription('The Cargo daemon client libraries to be used for this project.')
47 |
48 | configureAbstractContainerTask(project)
49 | }
50 |
51 | private void configureAbstractContainerTask(Project project) {
52 | project.tasks.withType(AbstractCargoContainerTask) {
53 | conventionMapping.map('classpath') {
54 | def config = project.configurations[CONFIGURATION_NAME]
55 |
56 | if(config.dependencies.empty) {
57 | project.dependencies {
58 | cargo "org.codehaus.cargo:cargo-core-uberjar:$CARGO_DEFAULT_VERSION",
59 | "org.codehaus.cargo:cargo-licensed-dtds:$CARGO_DEFAULT_VERSION",
60 | "org.codehaus.cargo:cargo-ant:$CARGO_DEFAULT_VERSION"
61 | }
62 | }
63 |
64 | config
65 | }
66 |
67 | conventionMapping.map('deployables') { resolveDeployables(project) }
68 | }
69 |
70 | project.tasks.withType(CargoDaemon) {
71 | conventionMapping.map('classpath') {
72 | def config = project.configurations[DAEMON_CONFIGURATION_NAME]
73 |
74 | if(config.dependencies.empty) {
75 | project.dependencies {
76 | cargoDaemon "org.codehaus.cargo:cargo-daemon-client:$CARGO_DEFAULT_VERSION"
77 | }
78 | }
79 |
80 | config
81 | }
82 | }
83 | }
84 |
85 | private List resolveDeployables(Project project) {
86 | def deployables = []
87 |
88 | Task projectDeployable = ProjectInfoHelper.getProjectDeployableTask(project)
89 |
90 | if(projectDeployable) {
91 | deployables << new Deployable(files: projectDeployable.outputs.files)
92 | }
93 |
94 | deployables
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/CargoPlugin.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo
17 |
18 | import com.bmuschko.gradle.cargo.convention.CargoPluginExtension
19 | import com.bmuschko.gradle.cargo.convention.Deployable
20 | import com.bmuschko.gradle.cargo.tasks.AbstractCargoContainerTask
21 | import com.bmuschko.gradle.cargo.tasks.local.*
22 | import com.bmuschko.gradle.cargo.tasks.remote.CargoDeployRemote
23 | import com.bmuschko.gradle.cargo.tasks.remote.CargoRedeployRemote
24 | import com.bmuschko.gradle.cargo.tasks.remote.CargoUndeployRemote
25 | import com.bmuschko.gradle.cargo.tasks.remote.RemoteCargoContainerTask
26 | import com.bmuschko.gradle.cargo.util.ProjectInfoHelper
27 | import org.gradle.api.InvalidUserDataException
28 | import org.gradle.api.Plugin
29 | import org.gradle.api.Project
30 | import org.gradle.api.Task
31 | import org.gradle.api.execution.TaskExecutionGraph
32 |
33 | /**
34 | * A {@link org.gradle.api.Plugin} that provides pre-configured tasks for deploying WAR/EAR files to local and remote web containers.
35 | */
36 | class CargoPlugin implements Plugin {
37 | static final String EXTENSION_NAME = 'cargo'
38 |
39 | @Override
40 | void apply(Project project) {
41 | project.plugins.apply(CargoBasePlugin)
42 |
43 | CargoPluginExtension cargoPluginExtension = project.extensions.create(EXTENSION_NAME, CargoPluginExtension, project)
44 |
45 | configureAbstractContainerTask(project, cargoPluginExtension)
46 | configureRemoteContainerTasks(project, cargoPluginExtension)
47 | configureLocalContainerTasks(project, cargoPluginExtension)
48 | checkValidContainerId(project, cargoPluginExtension)
49 | }
50 |
51 | private void configureAbstractContainerTask(Project project, CargoPluginExtension cargoPluginExtension) {
52 | project.tasks.withType(AbstractCargoContainerTask) {
53 | conventionMapping.map('containerId') { cargoPluginExtension.containerId }
54 | conventionMapping.map('port') { cargoPluginExtension.port }
55 | conventionMapping.map('deployables') { resolveDeployables(project, cargoPluginExtension) }
56 | }
57 | }
58 |
59 | private void configureLocalContainerConventionMapping(Project project, CargoPluginExtension cargoPluginExtension) {
60 | project.tasks.withType(LocalCargoContainerTask) {
61 | conventionMapping.map('jvmArgs') { cargoPluginExtension.local.jvmArgs }
62 | conventionMapping.map('logLevel') { cargoPluginExtension.local.logLevel }
63 | conventionMapping.map('homeDir') { cargoPluginExtension.local.homeDir }
64 | conventionMapping.map('configType') { cargoPluginExtension.local.configType }
65 | conventionMapping.map('configHomeDir') { cargoPluginExtension.local.configHomeDir }
66 | conventionMapping.map('outputFile') { cargoPluginExtension.local.outputFile }
67 | conventionMapping.map('logFile') { cargoPluginExtension.local.logFile }
68 | conventionMapping.map('rmiPort') { cargoPluginExtension.local.rmiPort }
69 | conventionMapping.map('startStopTimeout') { cargoPluginExtension.startStopTimeout }
70 | conventionMapping.map('zipUrlInstaller') { cargoPluginExtension.local.zipUrlInstaller }
71 | conventionMapping.map('configFiles') { cargoPluginExtension.local.configFiles }
72 | conventionMapping.map('files') { cargoPluginExtension.local.files }
73 | conventionMapping.map('containerProperties') { cargoPluginExtension.local.containerProperties.properties }
74 | conventionMapping.map('systemProperties') { cargoPluginExtension.local.systemProperties.properties }
75 | conventionMapping.map('extraClasspath') { cargoPluginExtension.local.extraClasspath }
76 | conventionMapping.map('sharedClasspath') { cargoPluginExtension.local.sharedClasspath }
77 | }
78 | }
79 |
80 | private void setRemoteContainerConventionMapping(Project project, CargoPluginExtension cargoPluginExtension) {
81 | project.tasks.withType(RemoteCargoContainerTask) {
82 | conventionMapping.map('protocol') { cargoPluginExtension.remote.protocol }
83 | conventionMapping.map('hostname') { cargoPluginExtension.remote.hostname }
84 | conventionMapping.map('username') { cargoPluginExtension.remote.username }
85 | conventionMapping.map('password') { cargoPluginExtension.remote.password }
86 | conventionMapping.map('containerProperties') { cargoPluginExtension.remote.containerProperties.properties }
87 | }
88 | }
89 |
90 | private void configureRemoteContainerTasks(Project project, CargoPluginExtension cargoPluginExtension) {
91 | setRemoteContainerConventionMapping(project, cargoPluginExtension)
92 | project.task('cargoDeployRemote', type: CargoDeployRemote)
93 | project.task('cargoUndeployRemote', type: CargoUndeployRemote)
94 | project.task('cargoRedeployRemote', type: CargoRedeployRemote)
95 | }
96 |
97 | private void configureLocalContainerTasks(Project project, CargoPluginExtension cargoPluginExtension) {
98 | configureLocalContainerConventionMapping(project, cargoPluginExtension)
99 | project.task('cargoRunLocal', type: CargoRunLocal)
100 | project.task('cargoStartLocal', type: CargoStartLocal)
101 | project.task('cargoStopLocal', type: CargoStopLocal)
102 | project.task('cargoRedeployLocal', type: CargoRedeployLocal)
103 | project.task('cargoConfigureLocal', type: CargoConfigureLocal)
104 | }
105 |
106 | private void checkValidContainerId(Project project, CargoPluginExtension cargoPluginExtension) {
107 | project.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
108 | if(containsCargoTask(taskGraph)) {
109 | if(!cargoPluginExtension.containerId) {
110 | throw new InvalidUserDataException('Container ID was not defined.')
111 | }
112 | }
113 | }
114 | }
115 |
116 | private boolean containsCargoTask(TaskExecutionGraph taskGraph) {
117 | taskGraph.allTasks.findAll { task -> task instanceof AbstractCargoContainerTask }.size() > 0
118 | }
119 |
120 | private List resolveDeployables(Project project, CargoPluginExtension cargoConvention) {
121 | def deployables = []
122 |
123 | Task projectDeployable = ProjectInfoHelper.getProjectDeployableTask(project)
124 |
125 | if (cargoConvention.deployables.size() == 0) {
126 | if (projectDeployable) {
127 | deployables << new Deployable(files: projectDeployable.outputs.files)
128 | }
129 | } else {
130 | cargoConvention.deployables.each { deployable ->
131 | if (!deployable.files && projectDeployable) {
132 | deployable.files = projectDeployable.outputs.files
133 | }
134 |
135 | deployables << deployable
136 | }
137 | }
138 |
139 | deployables
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/DeployableType.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo
17 |
18 | import groovy.util.logging.Slf4j
19 |
20 | /**
21 | * Type of deployable.
22 | */
23 | @Slf4j
24 | enum DeployableType {
25 | WAR('war'), EAR('ear'), EXPLODED('war')
26 |
27 | final String type
28 |
29 | private DeployableType(String type) {
30 | this.type = type
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/DeployableTypeFactory.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo
2 |
3 | import com.bmuschko.gradle.cargo.util.DefaultFileUtil
4 | import com.bmuschko.gradle.cargo.util.FileUtil
5 |
6 | @Singleton
7 | class DeployableTypeFactory {
8 | FileUtil fileUtil = new DefaultFileUtil()
9 |
10 | DeployableType getType(File file) {
11 | String filenameExtension = fileUtil.getExtension(file)
12 |
13 | switch(filenameExtension) {
14 | case 'war': return DeployableType.WAR
15 | case 'ear': return DeployableType.EAR
16 | case '': return DeployableType.EXPLODED
17 | default: throw new IllegalArgumentException("Unknown deployable type for file extension '$filenameExtension'")
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/BinFile.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | /**
19 | * Defines a binary file to be used in a local container.
20 | */
21 | class BinFile implements Serializable {
22 |
23 | /**
24 | * This specifies the path to the file that should be used.
25 | * Can also specify a directory path if a whole directory needs to be copied over.
26 | */
27 | File file
28 |
29 | /**
30 | * This specified the name the directory that the file should be copied to relative to the configurations home.
31 | */
32 | String toDir
33 |
34 | @Override
35 | boolean equals(o) {
36 | if (this.is(o)) return true
37 | if (getClass() != o.class) return false
38 |
39 | BinFile binFile = (BinFile) o
40 |
41 | if (file != binFile.file) return false
42 | if (toDir != binFile.toDir) return false
43 |
44 | return true
45 | }
46 |
47 | @Override
48 | int hashCode() {
49 | int result
50 | result = (file != null ? file.hashCode() : 0)
51 | result = 31 * result + (toDir != null ? toDir.hashCode() : 0)
52 | return result
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/CargoLocalTaskConvention.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | import org.gradle.api.file.FileCollection
19 |
20 | /**
21 | * Defines Cargo local task convention.
22 | */
23 | class CargoLocalTaskConvention {
24 |
25 | String jvmArgs
26 | String logLevel
27 | File homeDir
28 | String configType
29 | File configHomeDir
30 | File outputFile
31 | File logFile
32 | Integer rmiPort
33 | ZipUrlInstaller zipUrlInstaller = new ZipUrlInstaller()
34 | def configFiles = []
35 | def files = []
36 | ContainerProperties containerProperties = new ContainerProperties()
37 | SystemProperties systemProperties = new SystemProperties()
38 | FileCollection extraClasspath
39 | FileCollection sharedClasspath
40 |
41 | def installer(Closure closure) {
42 | closure.resolveStrategy = Closure.DELEGATE_FIRST
43 | closure.delegate = zipUrlInstaller
44 | closure()
45 | }
46 |
47 | def configFile(Closure closure) {
48 | closure.resolveStrategy = Closure.DELEGATE_FIRST
49 | ConfigFile configFile = new ConfigFile()
50 | closure.delegate = configFile
51 | configFiles << configFile
52 | closure()
53 | }
54 |
55 | def file(Closure closure) {
56 | closure.resolveStrategy = Closure.DELEGATE_FIRST
57 | BinFile file = new BinFile()
58 | closure.delegate = file
59 | files << file
60 | closure()
61 | }
62 |
63 | def containerProperties(Closure closure) {
64 | closure.resolveStrategy = Closure.DELEGATE_FIRST
65 | closure.delegate = containerProperties
66 | closure()
67 | }
68 |
69 | def systemProperties(Closure closure) {
70 | closure.resolveStrategy = Closure.DELEGATE_FIRST
71 | closure.delegate = systemProperties
72 | closure()
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/CargoPluginExtension.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | import org.gradle.api.Project
19 |
20 | /**
21 | * Defines Cargo extension.
22 | */
23 | class CargoPluginExtension {
24 |
25 | private final Project project
26 |
27 | String containerId
28 | Integer port = 8080
29 | Integer startStopTimeout
30 | def deployables = []
31 | CargoRemoteTaskConvention remote = new CargoRemoteTaskConvention()
32 | CargoLocalTaskConvention local = new CargoLocalTaskConvention()
33 |
34 | CargoPluginExtension(Project project) {
35 | this.project = project
36 | }
37 |
38 | def cargo(Closure closure) {
39 | closure.delegate = this
40 | closure()
41 | }
42 |
43 | def deployable(Closure closure) {
44 | closure.resolveStrategy = Closure.DELEGATE_FIRST
45 | def deployableClosureDelegate = new DeployableClosureDelegate(project)
46 | closure.delegate = deployableClosureDelegate
47 | deployables << deployableClosureDelegate.deployable
48 | closure()
49 | }
50 |
51 | def remote(Closure closure) {
52 | closure.resolveStrategy = Closure.DELEGATE_FIRST
53 | closure.delegate = remote
54 | closure()
55 | }
56 |
57 | def local(Closure closure) {
58 | closure.resolveStrategy = Closure.DELEGATE_FIRST
59 | closure.delegate = local
60 | closure()
61 | }
62 |
63 | private static class DeployableClosureDelegate {
64 |
65 | @Delegate
66 | final Deployable deployable = new Deployable()
67 | private final Project project
68 |
69 | DeployableClosureDelegate(Project project) {
70 | this.project = project
71 | }
72 |
73 | void setFile(Object file) {
74 | deployable.files = project.files(file)
75 | }
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/CargoRemoteTaskConvention.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | /**
19 | * Defines Cargo remote task convention.
20 | */
21 | class CargoRemoteTaskConvention {
22 | String protocol = 'http'
23 | String hostname
24 | String username
25 | String password
26 | ContainerProperties containerProperties = new ContainerProperties()
27 |
28 | def containerProperties(Closure closure) {
29 | closure.resolveStrategy = Closure.DELEGATE_FIRST
30 | closure.delegate = containerProperties
31 | closure()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/ConfigFile.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | import org.gradle.api.file.FileCollection
19 | import org.gradle.api.tasks.Input
20 | import org.gradle.api.tasks.InputFiles
21 |
22 | /**
23 | * Defines ConfigFile convention.
24 | */
25 | class ConfigFile {
26 |
27 | /**
28 | * This specifies the files that should be copied over.
29 | * Can also specify directories if whole directories need to be copied over.
30 | */
31 | @InputFiles
32 | FileCollection files
33 |
34 | /**
35 | * This specified the name the directory that the file should be copied to relative to the configurations home.
36 | */
37 | @Input
38 | String toDir
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/ContainerProperties.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | /**
19 | * Container-specific properties.
20 | */
21 | class ContainerProperties {
22 | Map properties = [:]
23 |
24 | void property(String key, Object value) {
25 | properties[key] = value
26 | }
27 |
28 | void properties(Map properties) {
29 | this.properties.putAll(properties)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/Deployable.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 |
19 | import org.gradle.api.file.FileCollection
20 | import org.gradle.api.tasks.Input
21 | import org.gradle.api.tasks.InputFiles
22 | import org.gradle.api.tasks.Internal
23 | import org.gradle.api.tasks.Optional
24 |
25 | /**
26 | * Defines Deployable convention.
27 | */
28 | class Deployable implements Serializable {
29 |
30 | @InputFiles
31 | FileCollection files
32 |
33 | @Input
34 | @Optional
35 | String context
36 |
37 | @Internal
38 | File getFile() {
39 | files?.singleFile
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/SystemProperties.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | /**
19 | * Properties that can be passed on to the local container.
20 | */
21 | class SystemProperties {
22 | Map properties = [:]
23 |
24 | void property(String key, Object value) {
25 | properties[key] = value
26 | }
27 |
28 | void properties(Map properties) {
29 | this.properties.putAll(properties)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/convention/ZipUrlInstaller.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.convention
17 |
18 | import org.gradle.api.file.FileCollection
19 | import org.gradle.api.tasks.Input
20 | import org.gradle.api.tasks.InputFiles
21 | import org.gradle.api.tasks.Internal
22 | import org.gradle.api.tasks.Optional
23 | import org.gradle.api.tasks.OutputDirectory
24 |
25 | import java.util.function.Supplier
26 |
27 | /**
28 | * ZIP URL installer properties.
29 | *
30 | * @see Installer documentation
31 | */
32 | class ZipUrlInstaller {
33 |
34 | private Supplier installUrlSupplier = { null }
35 |
36 | @Input
37 | @Optional
38 | String installUrl
39 |
40 | @InputFiles
41 | @Optional
42 | FileCollection installConfiguration
43 |
44 | @OutputDirectory
45 | @Optional
46 | File downloadDir
47 |
48 | @OutputDirectory
49 | @Optional
50 | File extractDir
51 |
52 | @Internal
53 | String getConfiguredInstallUrl() {
54 | installUrlSupplier.get()
55 | }
56 |
57 | @Internal
58 | boolean isValid() {
59 | configuredInstallUrl && downloadDir && extractDir
60 | }
61 |
62 | void setInstallUrl(String installUrl) {
63 | this.installUrl = installUrl
64 | this.installConfiguration = null
65 | installUrlSupplier = { installUrl }
66 | }
67 |
68 | void setInstallConfiguration(FileCollection configuration) {
69 | this.installUrl = null
70 | this.installConfiguration = configuration
71 | installUrlSupplier = { configuration.singleFile.toURI().toURL().toString() }
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/AbstractCargoContainerTask.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks
17 |
18 | import com.bmuschko.gradle.cargo.convention.Deployable
19 | import com.bmuschko.gradle.cargo.util.LoggingHandler
20 | import org.gradle.api.DefaultTask
21 | import org.gradle.api.InvalidUserDataException
22 | import org.gradle.api.file.FileCollection
23 | import org.gradle.api.tasks.Input
24 | import org.gradle.api.tasks.InputFiles
25 | import org.gradle.api.tasks.Nested
26 | import org.gradle.api.tasks.Optional
27 | import org.gradle.api.tasks.TaskAction
28 |
29 | /**
30 | * Abstract container task.
31 | */
32 | abstract class AbstractCargoContainerTask extends DefaultTask {
33 | static final String CARGO_TASK_GROUP = 'deployment'
34 | static final CARGO_TASKS = 'cargo.tasks'
35 | static final CARGO_SERVLET_PORT = 'cargo.servlet.port'
36 | static final CARGO_CONTEXT = 'context'
37 |
38 | /**
39 | * The Cargo container identifier.
40 | */
41 | @Input
42 | String containerId
43 |
44 | /**
45 | * The action to run for the container.
46 | */
47 | @Input
48 | String action
49 |
50 | /**
51 | * Port on which the Servlet/JSP container listens to.
52 | */
53 | @Input
54 | Integer port = 8080
55 |
56 | @Input
57 | @Optional
58 | String context
59 |
60 | /**
61 | * The classpath containing the Cargo Ant tasks.
62 | */
63 | @InputFiles
64 | FileCollection classpath
65 |
66 | /**
67 | * The list of deployable artifacts.
68 | */
69 | @Nested
70 | List deployables = []
71 |
72 | /**
73 | * Container properties.
74 | */
75 | @Input
76 | Map containerProperties = [:]
77 |
78 | AbstractCargoContainerTask() {
79 | group = CARGO_TASK_GROUP
80 |
81 | // No matter what the inputs and outputs make sure that run tasks are never up-to-date
82 | outputs.upToDateWhen {
83 | false
84 | }
85 | }
86 |
87 | @TaskAction
88 | void start() {
89 | validateConfiguration()
90 |
91 | LoggingHandler.withAntLoggingListener(ant) {
92 | runAction()
93 | }
94 | }
95 |
96 | void validateConfiguration() {
97 | if(!getDeployables()) {
98 | throw new InvalidUserDataException('No deployables assigned!')
99 | }
100 | }
101 |
102 | protected void setContainerSpecificProperties() {
103 | logger.info "Container properties = ${getContainerProperties()}"
104 |
105 | getContainerProperties().each { key, value ->
106 | ant.property(name: key, value: value)
107 | }
108 | }
109 |
110 | protected abstract void runAction()
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/daemon/CargoDaemon.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.daemon
17 |
18 | import org.gradle.api.DefaultTask
19 | import org.gradle.api.UncheckedIOException
20 | import org.gradle.api.file.FileCollection
21 | import org.gradle.api.tasks.Input
22 | import org.gradle.api.tasks.InputFiles
23 | import org.gradle.api.tasks.Optional
24 | import org.gradle.api.tasks.TaskAction
25 |
26 | import java.lang.reflect.Constructor
27 |
28 | abstract class CargoDaemon extends DefaultTask {
29 | @InputFiles
30 | FileCollection classpath
31 |
32 | /**
33 | * Protocol on which the container is listening to. Defaults to 'http'.
34 | */
35 | @Input
36 | String protocol = 'http'
37 |
38 | /**
39 | * Host name on which the container listens to. Defaults to 'localhost'.
40 | */
41 | @Input
42 | String hostname = 'localhost'
43 |
44 | /**
45 | * Port on which the daemon listens to.
46 | */
47 | @Input
48 | Integer port = 18000
49 |
50 | /**
51 | * Username to use to authenticate against a remote container.
52 | */
53 | @Input
54 | @Optional
55 | String username
56 |
57 | /**
58 | * Password to use to authenticate against a remote container.
59 | */
60 | @Input
61 | @Optional
62 | String password
63 |
64 | /**
65 | * The handle ID identifying a specific container configuration.
66 | */
67 | @Input
68 | String handleId
69 |
70 | @TaskAction
71 | void messageDaemon() {
72 | withCargoDaemonClassLoader { URLClassLoader classLoader ->
73 | def daemonClient = createDaemonClient(classLoader)
74 | performDaemonOperation(daemonClient, classLoader)
75 | }
76 | }
77 |
78 | def createDaemonClient(URLClassLoader classLoader) {
79 | URL daemonURL = new URL("${getProtocol()}://${getHostname()}:${getPort()}")
80 | Class daemonClientClass = classLoader.loadClass('org.codehaus.cargo.tools.daemon.DaemonClient')
81 | def daemonClient
82 |
83 | if(!isBlank(getUsername()) && !isBlank(getPassword())) {
84 | Constructor daemonClientConstructor = daemonClientClass.getConstructor(URL, String, String)
85 | daemonClient = daemonClientConstructor.newInstance(daemonURL, getUsername(), getPassword())
86 | }
87 | else if(!isBlank(getUsername())) {
88 | Constructor daemonClientConstructor = daemonClientClass.getConstructor(URL, String)
89 | daemonClient = daemonClientConstructor.newInstance(daemonURL, getUsername())
90 | }
91 | else {
92 | Constructor daemonClientConstructor = daemonClientClass.getConstructor(URL)
93 | daemonClient = daemonClientConstructor.newInstance(daemonURL)
94 | }
95 |
96 | daemonClient
97 | }
98 |
99 | private boolean isBlank(String parameter) {
100 | parameter != null && parameter.length() > 0
101 | }
102 |
103 | abstract void performDaemonOperation(daemonClient, URLClassLoader classLoader)
104 |
105 | private void withCargoDaemonClassLoader(Closure c) {
106 | ClassLoader originalClassLoader = getClass().classLoader
107 | URLClassLoader cargoDaemonClassloader = createCargoDaemonClassLoader()
108 |
109 | try {
110 | Thread.currentThread().contextClassLoader = cargoDaemonClassloader
111 | c(cargoDaemonClassloader)
112 | }
113 | finally {
114 | Thread.currentThread().contextClassLoader = originalClassLoader
115 | }
116 | }
117 |
118 | private URLClassLoader createCargoDaemonClassLoader() {
119 | new URLClassLoader(toURLArray(getClasspath().files), ClassLoader.systemClassLoader.parent)
120 | }
121 |
122 | private URL[] toURLArray(Collection files) {
123 | List urls = new ArrayList(files.size())
124 |
125 | for(File file : files) {
126 | try {
127 | urls.add(file.toURI().toURL())
128 | }
129 | catch(MalformedURLException e) {
130 | throw new UncheckedIOException(e)
131 | }
132 | }
133 |
134 | urls.toArray(new URL[urls.size()]);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/daemon/CargoDaemonStart.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.daemon
17 |
18 | /**
19 | * Starts the configured container via the Cargo daemon process.
20 | */
21 | class CargoDaemonStart extends CargoDaemon {
22 | @Override
23 | void performDaemonOperation(daemonClient, URLClassLoader classLoader) {
24 | logger.info "Starting container with handle ID '${getHandleId()}' over daemon URL '${daemonClient.getURL()}'."
25 | Class daemonStartClass = classLoader.loadClass('org.codehaus.cargo.tools.daemon.DaemonStart')
26 | def request = daemonStartClass.newInstance()
27 | request.handleId = getHandleId()
28 | daemonClient.start(request)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/daemon/CargoDaemonStop.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.daemon
17 |
18 | /**
19 | * Stops the configured container via the Cargo daemon process.
20 | */
21 | class CargoDaemonStop extends CargoDaemon {
22 | @Override
23 | void performDaemonOperation(daemonClient, URLClassLoader classLoader) {
24 | logger.info "Stopping container with handle ID '${getHandleId()}' over daemon URL '${daemonClient.getURL()}'."
25 | daemonClient.stop(getHandleId())
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/CargoConfigureLocal.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.tasks.local
2 |
3 | class CargoConfigureLocal extends LocalCargoContainerTask {
4 | CargoConfigureLocal() {
5 | action = 'configure'
6 | description = 'Configures the local container.'
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/CargoRedeployLocal.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.local
17 |
18 | /**
19 | * Redeploys a deployable on local container.
20 | */
21 | class CargoRedeployLocal extends LocalCargoContainerTask {
22 | CargoRedeployLocal() {
23 | action = 'redeploy'
24 | description = 'Redeploys a deployable on local container.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/CargoRunLocal.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.local
17 |
18 | /**
19 | * Starts the local container, deploys web application to it and wait for the user to press CTRL + C to stop.
20 | */
21 | class CargoRunLocal extends LocalCargoContainerTask {
22 | CargoRunLocal() {
23 | action = 'run'
24 | description = 'Starts the container, deploys a deployable and waits for the user to press CTRL + C to stop.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/CargoStartLocal.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.local
17 |
18 | /**
19 | * Starts the local container, deploys web application to it and then do other tasks (for example, execute tests).
20 | */
21 | class CargoStartLocal extends LocalCargoContainerTask {
22 | CargoStartLocal() {
23 | action = 'start'
24 | description = 'Starts the container, deploys a deployable and then do other tasks (for example, execute tests).'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/CargoStopLocal.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.local
17 |
18 | /**
19 | * Stops local container.
20 | */
21 | class CargoStopLocal extends LocalCargoContainerTask {
22 | CargoStopLocal() {
23 | action = 'stop'
24 | description = 'Stops local container.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/local/LocalCargoContainerTask.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.local
17 |
18 | import com.bmuschko.gradle.cargo.DeployableType
19 | import com.bmuschko.gradle.cargo.DeployableTypeFactory
20 | import com.bmuschko.gradle.cargo.convention.BinFile
21 | import com.bmuschko.gradle.cargo.convention.ConfigFile
22 | import com.bmuschko.gradle.cargo.convention.Deployable
23 | import com.bmuschko.gradle.cargo.convention.ZipUrlInstaller
24 | import com.bmuschko.gradle.cargo.tasks.AbstractCargoContainerTask
25 | import org.gradle.api.InvalidUserDataException
26 | import org.gradle.api.file.FileCollection
27 | import org.gradle.api.tasks.*
28 |
29 | /**
30 | * Deploys WAR to local container.
31 | */
32 | class LocalCargoContainerTask extends AbstractCargoContainerTask {
33 | /**
34 | * Level representing the quantity of information we wish to log.
35 | */
36 | @Input
37 | @Optional
38 | String logLevel
39 |
40 | /**
41 | * JVM args to be used when starting/stopping containers.
42 | */
43 | @Input
44 | @Optional
45 | String jvmArgs
46 |
47 | /**
48 | * The container's installation home directory.
49 | */
50 | @Internal
51 | @Optional
52 | File homeDir
53 |
54 | /**
55 | * The Cargo configuration home directory.
56 | */
57 | @Internal
58 | @Optional
59 | File configHomeDir
60 |
61 | /**
62 | * The Cargo configuration type.
63 | */
64 | @Internal
65 | @Optional
66 | String configType
67 |
68 | /**
69 | * The path to a file where container logs are saved.
70 | */
71 | @OutputFile
72 | @Optional
73 | File outputFile
74 |
75 | /**
76 | * The path to a file where Cargo logs are saved.
77 | */
78 | @OutputFile
79 | @Optional
80 | File logFile
81 |
82 | /**
83 | * The port to use when communicating with this server.
84 | */
85 | @Input
86 | @Optional
87 | Integer rmiPort
88 |
89 | /**
90 | * Timeout after which the container start/stop is deemed failed.
91 | */
92 | @Input
93 | @Optional
94 | Integer startStopTimeout
95 |
96 | /**
97 | * The system properties passed-on the container.
98 | */
99 | @Input
100 | Map systemProperties = [:]
101 |
102 | /**
103 | * The list of configuration files.
104 | */
105 | @Nested
106 | List configFiles = []
107 |
108 | /**
109 | * The list of binary files.
110 | */
111 | @Input
112 | List files = []
113 |
114 | /**
115 | * Configurable ZIP URL installer instance for automatically downloading a container.
116 | */
117 | @Nested
118 | ZipUrlInstaller zipUrlInstaller = new ZipUrlInstaller()
119 |
120 | /**
121 | * Additional libraries for your application's classpath that are not exposed to the container.
122 | */
123 | @InputFiles
124 | @Optional
125 | FileCollection sharedClasspath
126 |
127 | /**
128 | * Additional libraries added to the container's classpath.
129 | */
130 | @InputFiles
131 | @Optional
132 | FileCollection extraClasspath
133 |
134 | @Override
135 | void validateConfiguration() {
136 | super.validateConfiguration()
137 |
138 | if(!getDeployables().isEmpty()) {
139 | getDeployables().each { deployable ->
140 | if(deployable.file && !deployable.file.exists()) {
141 | throw new InvalidUserDataException("Deployable "
142 | + (deployable.file == null ? "null" : deployable.file.canonicalPath)
143 | + " does not exist")
144 | }
145 | }
146 |
147 | logger.info "Deployable artifacts = ${getDeployables().collect { it.file.canonicalPath }}"
148 | }
149 |
150 | if(!getConfigFiles().isEmpty()) {
151 | getConfigFiles().each { configFile ->
152 | configFile.files.each { file ->
153 | if (!file.exists()) {
154 | throw new InvalidUserDataException("Config file " + file.canonicalPath + " does not exist")
155 | }
156 | }
157 | }
158 |
159 | logger.info "Config files = ${getConfigFiles().collect { it.files*.canonicalPath + " -> " + it.toDir }}"
160 | }
161 |
162 | if (!getFiles().isEmpty()) {
163 | getFiles().each { binFile ->
164 | if (!binFile.file || !binFile.file.exists()) {
165 | throw new InvalidUserDataException("Binary File "
166 | + (binFile.file == null ? "null" : binFile.file.canonicalPath)
167 | + " does not exist")
168 | }
169 | }
170 | logger.info "Binary files = ${getFiles().collect { it.file.canonicalPath + " -> " + it.toDir }}"
171 | }
172 |
173 | if (getConfigType()) {
174 | if (!['standalone','existing'].contains(getConfigType())) {
175 | throw new InvalidUserDataException("Configuration type " + getConfigType() + " is not supported, use 'standalone' or 'existing'")
176 | }
177 | }
178 | }
179 |
180 | @Input
181 | @Optional
182 | protected String getHomeDirPath() {
183 | getHomeDir()?.canonicalPath
184 | }
185 |
186 | @Override
187 | void runAction() {
188 | logger.info "Starting action '${getAction()}' for local container '${getContainerId()}'"
189 |
190 | ant.taskdef(resource: AbstractCargoContainerTask.CARGO_TASKS, classpath: getClasspath().asPath)
191 | ant.cargo(getCargoAttributes()) {
192 | ant.configuration(getConfigurationAttributes()) {
193 | property(name: AbstractCargoContainerTask.CARGO_SERVLET_PORT, value: getPort())
194 |
195 | if(getJvmArgs()) {
196 | ant.property(name: 'cargo.jvmargs', value: getJvmArgs())
197 | }
198 |
199 | if(getLogLevel()) {
200 | ant.property(name: 'cargo.logging', value: getLogLevel())
201 | }
202 |
203 | if(getRmiPort()) {
204 | ant.property(name: 'cargo.rmi.port', value: getRmiPort())
205 | }
206 |
207 | setContainerSpecificProperties()
208 |
209 | getDeployables().each { Deployable deployable ->
210 | DeployableType deployableType = DeployableTypeFactory.instance.getType(deployable.file)
211 |
212 | if(deployable.context) {
213 | ant.deployable(type: deployableType.type, file: deployable.file) {
214 | ant.property(name: AbstractCargoContainerTask.CARGO_CONTEXT, value: deployable.context)
215 | }
216 | }
217 | else {
218 | ant.deployable(type: deployableType.type, file: deployable.file)
219 | }
220 | }
221 |
222 | getConfigFiles().each { configFile ->
223 | configFile.files.each { file ->
224 | ant.configfile(file: file, todir: configFile.toDir)
225 | }
226 | }
227 |
228 | getFiles().each { binFile ->
229 | ant.file(file: binFile.file, todir: binFile.toDir)
230 | }
231 | }
232 |
233 | setSystemProperties()
234 |
235 | if(getZipUrlInstaller().isValid()) {
236 | ant.zipUrlInstaller(installUrl: getZipUrlInstaller().configuredInstallUrl, downloadDir: getZipUrlInstaller().downloadDir,
237 | extractDir: getZipUrlInstaller().extractDir)
238 | }
239 |
240 | if(getExtraClasspath()) {
241 | ant.extraClasspath() {
242 | getExtraClasspath().addToAntBuilder(ant, 'fileset', FileCollection.AntType.FileSet)
243 | }
244 | }
245 |
246 | if(getSharedClasspath()) {
247 | ant.sharedClasspath() {
248 | getSharedClasspath().addToAntBuilder(ant, 'fileset', FileCollection.AntType.FileSet)
249 | }
250 | }
251 | }
252 | }
253 |
254 | @Input
255 | protected Map getConfigurationAttributes() {
256 | def config = [:]
257 |
258 | if(getConfigHomeDir()) {
259 | if(!getConfigHomeDir().exists()) {
260 | ant.mkdir(getConfigHomeDir())
261 | }
262 |
263 | config['home'] = getConfigHomeDir().absolutePath
264 | }
265 |
266 | if(getConfigType()) {
267 | config['type'] = getConfigType()
268 | }
269 |
270 | return config
271 | }
272 |
273 | private Map getCargoAttributes() {
274 | def cargoAttributes = ['containerId': getContainerId(), 'action': getAction()]
275 | if (getStartStopTimeout() >= 0) {
276 | cargoAttributes['timeout'] = getStartStopTimeout()
277 | }
278 |
279 | if(!getZipUrlInstaller().isValid()) {
280 | cargoAttributes['home'] = homeDirPath
281 | }
282 |
283 | if(getOutputFile()) {
284 | cargoAttributes['output'] = getOutputFile()
285 | }
286 |
287 | if(getLogFile()) {
288 | cargoAttributes['log'] = getLogFile()
289 | }
290 |
291 | cargoAttributes
292 | }
293 |
294 | void setSystemProperties() {
295 | logger.info "System properties = ${getSystemProperties()}"
296 |
297 | getSystemProperties().each { key, value ->
298 | ant.sysproperty(key: key, value: value)
299 | }
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/remote/CargoDeployRemote.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.remote
17 |
18 | /**
19 | * Deploys web application to remote container.
20 | */
21 | class CargoDeployRemote extends RemoteCargoContainerTask {
22 | CargoDeployRemote() {
23 | action = 'deploy'
24 | description = 'Deploys a deployable to remote container.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/remote/CargoRedeployRemote.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.remote
17 |
18 | /**
19 | * Redeploys web application to remote container.
20 | */
21 | class CargoRedeployRemote extends RemoteCargoContainerTask {
22 | CargoRedeployRemote() {
23 | action = 'redeploy'
24 | description = 'Redeploys a deployable to remote container.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/remote/CargoUndeployRemote.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.remote
17 |
18 | /**
19 | * Undeploys a web application from remote container.
20 | */
21 | class CargoUndeployRemote extends RemoteCargoContainerTask {
22 | CargoUndeployRemote() {
23 | action = 'undeploy'
24 | description = 'Undeploys a deployable from remote container.'
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/tasks/remote/RemoteCargoContainerTask.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.tasks.remote
17 |
18 | import com.bmuschko.gradle.cargo.DeployableType
19 | import com.bmuschko.gradle.cargo.DeployableTypeFactory
20 | import com.bmuschko.gradle.cargo.convention.Deployable
21 | import com.bmuschko.gradle.cargo.tasks.AbstractCargoContainerTask
22 | import org.gradle.api.InvalidUserDataException
23 | import org.gradle.api.tasks.Input
24 |
25 | /**
26 | * Deploys WAR to remote container.
27 | */
28 | class RemoteCargoContainerTask extends AbstractCargoContainerTask {
29 | static final String UNDEPLOY_ACTION = 'undeploy'
30 |
31 | /**
32 | * Protocol on which the container is listening to. Defaults to 'http'.
33 | */
34 | @Input
35 | String protocol = 'http'
36 |
37 | /**
38 | * Host name on which the container listens to. Defaults to 'localhost'.
39 | */
40 | @Input
41 | String hostname = 'localhost'
42 |
43 | /**
44 | * Username to use to authenticate against a remote container.
45 | */
46 | @Input
47 | String username
48 |
49 | /**
50 | * Password to use to authenticate against a remote container.
51 | */
52 | @Input
53 | String password
54 |
55 | @Override
56 | void validateConfiguration() {
57 | super.validateConfiguration()
58 |
59 | if(getAction() != UNDEPLOY_ACTION) {
60 | getDeployables().each { deployable ->
61 | if(deployable.file && !deployable.file.exists()) {
62 | throw new InvalidUserDataException("Deployable "
63 | + (deployable.file == null ? "null" : deployable.file.canonicalPath)
64 | + " does not exist")
65 | }
66 |
67 | if(DeployableType.EXPLODED == DeployableTypeFactory.instance.getType(deployable.file)) {
68 | throw new InvalidUserDataException("Deployable type: EXPLODED is invalid for remote deployment")
69 | }
70 |
71 | logger.info "Deployable artifacts = ${getDeployables().collect { it.file.canonicalPath }}"
72 | }
73 | }
74 | }
75 |
76 | @Override
77 | void runAction() {
78 | logger.info "Starting action '${getAction()}' for remote container '${getContainerId()}' on '${getProtocol()}://${getHostname()}:${getPort()}'"
79 |
80 | ant.taskdef(resource: AbstractCargoContainerTask.CARGO_TASKS, classpath: getClasspath().asPath)
81 | ant.cargo(containerId: getContainerId(), type: 'remote', action: getAction()) {
82 | configuration(type: 'runtime') {
83 | property(name: 'cargo.protocol', value: getProtocol())
84 | property(name: 'cargo.hostname', value: getHostname())
85 | property(name: AbstractCargoContainerTask.CARGO_SERVLET_PORT, value: getPort())
86 | setContainerSpecificProperties()
87 |
88 | if(getUsername() && getPassword()) {
89 | property(name: 'cargo.remote.username', value: getUsername())
90 | property(name: 'cargo.remote.password', value: getPassword())
91 | }
92 |
93 | getDeployables().each { Deployable deployable ->
94 | DeployableType deployableType = DeployableTypeFactory.instance.getType(deployable.file)
95 |
96 | if(deployable.context) {
97 | // For the undeploy action do not set a file attribute
98 | if(getAction() == UNDEPLOY_ACTION) {
99 | ant.deployable(type: deployableType.type) {
100 | property(name: AbstractCargoContainerTask.CARGO_CONTEXT, value: deployable.context)
101 | }
102 | }
103 | else {
104 | ant.deployable(type: deployableType.type, file: deployable.file) {
105 | property(name: AbstractCargoContainerTask.CARGO_CONTEXT, value: deployable.context)
106 | }
107 | }
108 | }
109 | else {
110 | ant.deployable(type: deployableType.type, file: deployable.file)
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/util/CargoAntLoggingListener.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.apache.tools.ant.BuildEvent
19 | import org.apache.tools.ant.BuildListener
20 | import org.apache.tools.ant.Project
21 | import org.apache.tools.ant.Task
22 | import org.gradle.api.logging.Logger
23 | import org.gradle.api.logging.Logging
24 |
25 | /**
26 | * Cargo Ant build listener.
27 | */
28 | class CargoAntLoggingListener implements BuildListener {
29 | Logger logger = Logging.getLogger(CargoAntLoggingListener)
30 | static final String ANT_CARGO_TASK_NAME = 'org.codehaus.cargo.ant.CargoTask'
31 |
32 | @Override
33 | void buildStarted(BuildEvent buildEvent) {}
34 |
35 | @Override
36 | void buildFinished(BuildEvent buildEvent) {}
37 |
38 | @Override
39 | void targetStarted(BuildEvent buildEvent) {}
40 |
41 | @Override
42 | void targetFinished(BuildEvent buildEvent) {}
43 |
44 | @Override
45 | void taskStarted(BuildEvent buildEvent) {}
46 |
47 | @Override
48 | void taskFinished(BuildEvent buildEvent) {}
49 |
50 | /**
51 | * Wraps the subclasses action code in a listener that raises info priority Ant task messages to
52 | * be lifecycle messages for Gradle. This allows messages from the Ant task, such as
53 | * "Press Ctrl-C to stop the container..." to be passed through.
54 | *
55 | * @param buildEvent Build event
56 | */
57 | @Override
58 | void messageLogged(BuildEvent buildEvent) {
59 | if(buildEvent.task && isCargoTask(buildEvent.task) && isInfoPriority(buildEvent.priority)) {
60 | logger.lifecycle(buildEvent.message)
61 | }
62 | }
63 |
64 | private boolean isCargoTask(Task task) {
65 | task.class.canonicalName == ANT_CARGO_TASK_NAME
66 | }
67 |
68 | private boolean isInfoPriority(int priority) {
69 | priority == Project.MSG_INFO
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/util/DefaultFileUtil.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | /**
19 | * Filename utilities.
20 | */
21 | class DefaultFileUtil implements FileUtil {
22 | @Override
23 | String getExtension(File file) {
24 | if(!file.exists()) {
25 | throw new IllegalArgumentException("File '$file.canonicalPath' does not exist")
26 | }
27 |
28 | if(file.isDirectory()) {
29 | return ''
30 | }
31 |
32 | String filename = file.canonicalPath
33 | int index = filename.lastIndexOf('.')
34 |
35 | if (index > 0) {
36 | return filename.substring(index + 1)
37 | }
38 |
39 | ''
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/util/FileUtil.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | interface FileUtil {
19 | String getExtension(File file)
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/util/LoggingHandler.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.apache.tools.ant.BuildListener
19 | import org.gradle.api.AntBuilder
20 |
21 | /**
22 | * Logging handler support.
23 | */
24 | class LoggingHandler {
25 | /**
26 | * Attaches Ant logging handler for closure execution.
27 | *
28 | * @param antBuilder Ant builder
29 | * @param c Closure
30 | */
31 | static void withAntLoggingListener(AntBuilder antBuilder, Closure c) {
32 | BuildListener listener = new CargoAntLoggingListener()
33 |
34 | try {
35 | antBuilder.project.addBuildListener(listener)
36 | c()
37 | }
38 | finally {
39 | antBuilder.project.removeBuildListener(listener)
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/groovy/com/bmuschko/gradle/cargo/util/ProjectInfoHelper.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.gradle.api.Project
19 | import org.gradle.api.Task
20 | import org.gradle.api.plugins.WarPlugin
21 | import org.gradle.plugins.ear.EarPlugin
22 |
23 | /**
24 | * Provides helper method for retrieving project information.
25 | */
26 | final class ProjectInfoHelper {
27 | private ProjectInfoHelper() {}
28 |
29 | static Task getProjectDeployableTask(Project project) {
30 | if(project.plugins.hasPlugin(WarPlugin.WAR_TASK_NAME)) {
31 | return project.tasks.getByName(WarPlugin.WAR_TASK_NAME)
32 | }
33 | else if(project.plugins.hasPlugin(EarPlugin.EAR_TASK_NAME)) {
34 | return project.tasks.getByName(EarPlugin.EAR_TASK_NAME)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/groovy/com/bmuschko/gradle/cargo/util/CargoAntLoggingListenerSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.apache.tools.ant.BuildEvent
19 | import org.apache.tools.ant.BuildListener
20 | import org.apache.tools.ant.Project
21 | import org.apache.tools.ant.Task
22 | import org.apache.tools.ant.taskdefs.Copy
23 | import org.codehaus.cargo.ant.CargoTask
24 | import org.gradle.api.logging.Logger
25 | import spock.lang.Specification
26 |
27 | /**
28 | * Cargo Ant build listener unit tests.
29 | */
30 | class CargoAntLoggingListenerSpec extends Specification {
31 | BuildListener buildListener
32 |
33 | def setup() {
34 | buildListener = new CargoAntLoggingListener()
35 | }
36 |
37 | void "Message not logged for non-Cargo Ant task"() {
38 | given:
39 | Task antCopyTask = new Copy()
40 | BuildEvent buildEvent = new BuildEvent(antCopyTask)
41 | buildEvent.message = 'Cargo started'
42 | Logger mockLogger = Mock(Logger)
43 | buildListener.logger = mockLogger
44 | when:
45 | buildListener.messageLogged(buildEvent)
46 | then:
47 | 0 * mockLogger.lifecycle('Cargo started')
48 | }
49 |
50 | void "Message not logged for Cargo Ant task with debug priority"() {
51 | given:
52 | Task antCargoTask = new CargoTask()
53 | BuildEvent buildEvent = new BuildEvent(antCargoTask)
54 | buildEvent.message = 'Cargo started'
55 | buildEvent.priority = Project.MSG_DEBUG
56 | Logger mockLogger = Mock(Logger)
57 | buildListener.logger = mockLogger
58 | when:
59 | buildListener.messageLogged(buildEvent)
60 | then:
61 | 0 * mockLogger.lifecycle('Cargo started')
62 | }
63 |
64 | void "Message logged for Cargo Ant task with info priority"() {
65 | given:
66 | Task antCargoTask = new CargoTask()
67 | BuildEvent buildEvent = new BuildEvent(antCargoTask)
68 | buildEvent.message = 'Cargo started'
69 | buildEvent.priority = Project.MSG_INFO
70 | Logger mockLogger = Mock(Logger)
71 | buildListener.logger = mockLogger
72 | when:
73 | buildListener.messageLogged(buildEvent)
74 | then:
75 | 1 * mockLogger.lifecycle('Cargo started')
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/groovy/com/bmuschko/gradle/cargo/util/DefaultFileUtilSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.junit.Rule
19 | import org.junit.rules.TemporaryFolder
20 | import spock.lang.Specification
21 | import spock.lang.Unroll
22 |
23 | /**
24 | * Filename utilities unit tests.
25 | */
26 | class DefaultFileUtilSpec extends Specification {
27 | @Rule
28 | TemporaryFolder temporaryFolder = new TemporaryFolder()
29 |
30 | FileUtil fileUtil = new DefaultFileUtil()
31 |
32 | def "throws exception for non-existent file"() {
33 | when:
34 | fileUtil.getExtension(new File('unknownfile'))
35 |
36 | then:
37 | thrown(IllegalArgumentException)
38 | }
39 |
40 | @Unroll
41 | def "get file extension for file with name '#filename'"() {
42 | when:
43 | String extension = fileUtil.getExtension(temporaryFolder.newFile(filename))
44 |
45 | then:
46 | extension == expectedExtension
47 |
48 | where:
49 | filename | expectedExtension
50 | 'test.war' | 'war'
51 | 'test' | ''
52 | }
53 |
54 | @Unroll
55 | def "get file extension for directory with name '#dirname'"() {
56 | when:
57 | String extension = fileUtil.getExtension(temporaryFolder.newFolder(dirname))
58 |
59 | then:
60 | extension == expectedExtension
61 |
62 | where:
63 | dirname | expectedExtension
64 | 'test' | ''
65 | 'test-1.0' | ''
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/groovy/com/bmuschko/gradle/cargo/util/DeployableTypeFactorySpec.groovy:
--------------------------------------------------------------------------------
1 | package com.bmuschko.gradle.cargo.util
2 |
3 | import com.bmuschko.gradle.cargo.DeployableType
4 | import com.bmuschko.gradle.cargo.DeployableTypeFactory
5 | import spock.lang.Specification
6 | import spock.lang.Unroll
7 |
8 | class DeployableTypeFactorySpec extends Specification {
9 | FileUtil fileUtil = Mock()
10 |
11 | def setup() {
12 | DeployableTypeFactory.instance.fileUtil = fileUtil
13 | }
14 |
15 | @Unroll
16 | def "determines type for '#description'"() {
17 | given:
18 | File givenFile = new File(givenFilename)
19 |
20 | when:
21 | DeployableType deployableType = DeployableTypeFactory.instance.getType(givenFile)
22 |
23 | then:
24 | 1 * fileUtil.getExtension(givenFile) >> fileExtension
25 | deployableType.type == expectedDeployableType.type
26 |
27 | where:
28 | givenFilename | fileExtension | expectedDeployableType | description
29 | '/User/ben/app/myapp.war' | 'war' | DeployableType.WAR | 'WAR file'
30 | '/User/ben/app/myapp.ear' | 'ear' | DeployableType.EAR | 'EAR file'
31 | '/User/ben/app/myapp' | '' | DeployableType.EXPLODED | 'exploded WAR'
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/groovy/com/bmuschko/gradle/cargo/util/LoggingHandlerSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.bmuschko.gradle.cargo.util
17 |
18 | import org.gradle.api.Project
19 | import org.gradle.testfixtures.ProjectBuilder
20 | import spock.lang.Specification
21 |
22 | /**
23 | * Logging handler unit tests.
24 | */
25 | class LoggingHandlerSpec extends Specification {
26 | Project project
27 |
28 | def setup() {
29 | project = ProjectBuilder.builder().build()
30 | }
31 |
32 | void "Closure is executed"() {
33 | expect:
34 | project.ant.project.buildListeners.find { it.class == org.apache.tools.ant.BuildListener } == null
35 | boolean test = false
36 | when:
37 | LoggingHandler.withAntLoggingListener(project.ant) {
38 | test = true
39 | }
40 | then:
41 | test
42 | project.ant.project.buildListeners.find { it.class == org.apache.tools.ant.BuildListener } == null
43 | }
44 | }
45 |
--------------------------------------------------------------------------------