Relocate projects to spring-boot-project
Move projects to better reflect the way that Spring Boot is released. The following projects are under `spring-boot-project`: - `spring-boot` - `spring-boot-autoconfigure` - `spring-boot-tools` - `spring-boot-starters` - `spring-boot-actuator` - `spring-boot-actuator-autoconfigure` - `spring-boot-test` - `spring-boot-test-autoconfigure` - `spring-boot-devtools` - `spring-boot-cli` - `spring-boot-docs` See gh-9316
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
[[getting-started]]
|
||||
== Getting started
|
||||
|
||||
To get started with the plugin it needs to be applied to your project.
|
||||
|
||||
ifeval::["{version-type}" == "RELEASE"]
|
||||
The plugin is https://plugins.gradle.org/plugin/org.springframework.boot[published to
|
||||
Gradle's plugin portal] and can be applied using the `plugins` block:
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
include::../gradle/getting-started/apply-plugin-release.gradle[]
|
||||
----
|
||||
endif::[]
|
||||
ifeval::["{version-type}" == "MILESTONE"]
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
include::../gradle/getting-started/apply-plugin-milestone.gradle[]
|
||||
----
|
||||
endif::[]
|
||||
ifeval::["{version-type}" == "SNAPSHOT"]
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
include::../gradle/getting-started/apply-plugin-snapshot.gradle[]
|
||||
----
|
||||
endif::[]
|
||||
|
||||
Applied in isolation the plugin makes few changes to a project. Instead, the plugin
|
||||
detects when certain other plugins are applied and reacts accordingly. For example, when
|
||||
the `java` plugin is applied a task for building an executable jar is automatically
|
||||
configured.
|
||||
|
||||
A typical Spring Boot project will apply the {groovy-plugin}[`groovy`],
|
||||
{java-plugin}java_plugin.html[`java`], or {kotlin-plugin}[`org.jetbrains.kotlin.jvm`]
|
||||
plugin and the {dependency-management-plugin}[`io.spring.dependency-management`] plugin as
|
||||
a minimum. For example:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
include::../gradle/getting-started/typical-plugins.gradle[tags=apply]
|
||||
----
|
||||
|
||||
To learn more about how the Spring Boot plugin behaves when other plugins are applied
|
||||
please see the section on <<reacting-to-other-plugins, reacting to other plugins>>.
|
||||
@@ -0,0 +1,49 @@
|
||||
= Spring Boot Gradle Plugin Reference Guide
|
||||
Andy Wilkinson
|
||||
:doctype: book
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:source-highlighter: prettify
|
||||
:numbered:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin
|
||||
:dependency-management-plugin-documentation: {dependency-management-plugin}/blob/master/README.md
|
||||
:gradle-userguide: http://www.gradle.org/docs/current/userguide
|
||||
:gradle-dsl: https://docs.gradle.org/current/dsl
|
||||
:application-plugin: {gradle-userguide}/application_plugin.html
|
||||
:groovy-plugin: {gradle-userguide}/groovy_plugin.html
|
||||
:java-plugin: {gradle-userguide}/java_plugin.html
|
||||
:war-plugin: {gradle-userguide}/war_plugin.html
|
||||
:maven-plugin: {gradle-userguide}/maven_plugin.html
|
||||
:maven-publish-plugin: {gradle-userguide}/maven_publish_plugin.html
|
||||
:software-component: {gradle-userguide}/software_model_extend.html
|
||||
:kotlin-plugin: https://kotlinlang.org/docs/reference/using-gradle.html
|
||||
:spring-boot-docs: https://docs.spring.io/spring-boot/docs/{version}
|
||||
:api-documentation: {spring-boot-docs}/gradle-plugin/api
|
||||
:spring-boot-reference: {spring-boot-docs}/reference/htmlsingle
|
||||
:build-info-javadoc: {api-documentation}/org/springframework/boot/gradle/tasks/buildinfo/BuildInfo.html
|
||||
:boot-jar-javadoc: {api-documentation}/org/springframework/boot/gradle/tasks/bundling/BootJar.html
|
||||
:boot-war-javadoc: {api-documentation}/org/springframework/boot/gradle/tasks/bundling/BootWar.html
|
||||
:boot-run-javadoc: {api-documentation}/org/springframework/boot/gradle/tasks/run/BootRun.html
|
||||
:github-code: https://github.com/spring-projects/spring-boot/tree/{github-tag}
|
||||
|
||||
|
||||
|
||||
[[introduction]]
|
||||
== Introduction
|
||||
|
||||
The Spring Boot Gradle Plugin provides Spring Boot support in https://gradle.org[Gradle],
|
||||
allowing you to package executable jar or war archives, run Spring Boot applications, and
|
||||
use the dependency management provided by `spring-boot-dependencies`. Spring Boot's
|
||||
Gradle plugin requires Gradle 4.0 or later.
|
||||
|
||||
In addition to this user guide, {api-documentation}[API documentation] is also available.
|
||||
|
||||
include::getting-started.adoc[]
|
||||
include::managing-dependencies.adoc[]
|
||||
include::packaging.adoc[]
|
||||
include::publishing.adoc[]
|
||||
include::running.adoc[]
|
||||
include::integrating-with-actuator.adoc[]
|
||||
include::reacting.adoc[]
|
||||
@@ -0,0 +1,55 @@
|
||||
[[integrating-with-actuator]]
|
||||
== Integrating with Actuator
|
||||
|
||||
|
||||
[[integrating-with-actuator-build-info]]
|
||||
=== Generating build information
|
||||
|
||||
Spring Boot Actuator's `info` endpoint automatically publishes information about your
|
||||
build in the presence of a `META-INF/build-info.properties` file. A
|
||||
{build-info-javadoc}[`BuildInfo`] task is provided to generate this file. The easiest way
|
||||
to use the task is via the plugin's DSL:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/integrating-with-actuator/build-info-basic.gradle[tags=build-info]
|
||||
----
|
||||
|
||||
This will configure a {build-info-javadoc}[`BuildInfo`] task named `bootBuildInfo` and, if
|
||||
it exists, make the Java plugin's `classes` task depend upon it. The task's destination
|
||||
directory will be `META-INF` in the output directory of the main source set's resources
|
||||
(typically `build/resources/main`).
|
||||
|
||||
By default, the generated build information is derived from the project:
|
||||
|
||||
|===
|
||||
| Property | Default value
|
||||
|
||||
| `build.artifact`
|
||||
| The base name of the `bootJar` or `bootWar` task, or `unspecified` if no such task
|
||||
exists
|
||||
|
||||
| `build.group`
|
||||
| The group of the project
|
||||
|
||||
| `build.name`
|
||||
| The name of the project
|
||||
|
||||
| `build.version`
|
||||
| The version of the project
|
||||
|
||||
|===
|
||||
|
||||
The properties can be customized using the DSL:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tags=custom-values]
|
||||
----
|
||||
|
||||
Additional properties can also be added to the build information:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/integrating-with-actuator/build-info-additional.gradle[tags=additional]
|
||||
----
|
||||
@@ -0,0 +1,46 @@
|
||||
[[managing-dependencies]]
|
||||
== Managing dependencies
|
||||
|
||||
When you apply the {dependency-management-plugin}[`io.spring.dependency-management`]
|
||||
plugin, Spring Boot's plugin will
|
||||
automatically <<reacting-to-other-plugins-dependency-management,import the
|
||||
`spring-boot-dependencies` bom>> from the version of Spring Boot that you are using.
|
||||
This provides a similar dependency management experience to the one that's enjoyed by
|
||||
Maven users. For example, it allows you to omit version numbers when declaring
|
||||
dependencies that are managed in the bom. To make use of this functionality, simply
|
||||
declare dependencies in the usual way but omit the version number:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/managing-dependencies/dependencies.gradle[tags=dependencies]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[managing-dependencies-customizing]]
|
||||
=== Customizing managed versions
|
||||
|
||||
The `spring-boot-dependencies` bom that is automatically imported when the dependency
|
||||
management plugin is applied uses properties to control the versions of the dependencies
|
||||
that it manages. Please refer to the {github-code}/spring-boot-dependencies/pom.xml[bom]
|
||||
for a complete list of these properties.
|
||||
|
||||
To customize a managed version you set its corresponding property. For example, to
|
||||
customize the version of SLF4J which is controlled by the `slf4j.version` property:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/managing-dependencies/custom-version.gradle[tags=custom-version]
|
||||
----
|
||||
|
||||
WARNING: Each Spring Boot release is designed and tested against a specific set of
|
||||
third-party dependencies. Overriding versions may cause compatibility issues and should
|
||||
be done with care.
|
||||
|
||||
|
||||
|
||||
[[managing-dependencies-learning-more]]
|
||||
=== Learning more
|
||||
|
||||
To learn more about the capabilities of the dependency management plugin, please refer to
|
||||
its {dependency-management-plugin-documentation}[documentation].
|
||||
@@ -0,0 +1,192 @@
|
||||
[[packaging-executable]]
|
||||
== Packaging executable archives
|
||||
|
||||
The plugin can create executable archives (jar files and war files) that contain all of
|
||||
an application's dependencies and can then be run with `java -jar`.
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-jars]]
|
||||
=== Packaging executable jars
|
||||
|
||||
Executable jars can be built using the `bootJar` task. The task is automatically created
|
||||
when the `java` plugin is applied and is an instance of {boot-jar-javadoc}[`BootJar`].
|
||||
The `assemble` task is automatically configured to depend upon the `bootJar` task so
|
||||
running `assemble` (or `build`) will also run the `bootJar` task.
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-wars]]
|
||||
=== Packaging executable wars
|
||||
|
||||
Executable wars can be built using the `bootWar` task. The task is automatically created
|
||||
when the `war` plugin is applied and is an instance of {boot-war-javadoc}[`BootWar`].
|
||||
The `assemble` task is automatically configured to depend upon the `bootWar` task so
|
||||
running `assemble` (or `build`) will also run the `bootWar` task.
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-wars-deployable]]
|
||||
==== Packaging executable and deployable wars
|
||||
|
||||
A war file can be packaged such that it can be executed using `java -jar` and deployed
|
||||
to an external container. To do so, the embedded servlet container dependencies should
|
||||
be added to the `providedRuntime` configuration, for example:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/war-container-dependency.gradle[tags=dependencies]
|
||||
----
|
||||
|
||||
This ensures that they are package in the war file's `WEB-INF/lib-provided` directory
|
||||
from where they will not conflict with the external container's own classes.
|
||||
|
||||
NOTE: `providedRuntime` is preferred to Gradle's `compileOnly` configuration as, among
|
||||
other limitations, `compileOnly` dependencies are not on the test classpath so any
|
||||
web-based integration tests will fail.
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-and-normal]]
|
||||
=== Packaging executable and normal archives
|
||||
|
||||
By default, when the `bootJar` or `bootWar` tasks are configured, the `jar` or `war`
|
||||
tasks are disabled. A project can be configured to build both an executable archive
|
||||
and a normal archive at the same time by enabling the `jar` or `war` task:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=enable-jar]
|
||||
----
|
||||
|
||||
To avoid the executable archive and the normal archive from being written to the same
|
||||
location, one or the other should be configured to use a different location. One way to
|
||||
do so is by configuring a classifier:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=classifier]
|
||||
----
|
||||
|
||||
[[packaging-executable-configuring]]
|
||||
=== Configuring executable archive packaging
|
||||
|
||||
The {boot-jar-javadoc}[`BootJar`] and {boot-war-javadoc}[`BootWar`] tasks are subclasses
|
||||
of Gradle's `Jar` and `War` tasks respectively. As a result, all of the standard
|
||||
configuration options that are available when packaging a jar or war are also available
|
||||
when packaging an executable jar or war. A number of configuration options that are
|
||||
specific to executable jars and wars are also provided.
|
||||
|
||||
|
||||
[[packaging-executable-configuring-main-class]]
|
||||
==== Configuring the main class
|
||||
|
||||
By default, the executable archive's main class will be configured automatically by
|
||||
looking for a class with a `public static void main(String[])` method in directories on
|
||||
the task's classpath.
|
||||
|
||||
The main class can also be configured explicitly using the task's `mainClass` property:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-main-class.gradle[tags=main-class]
|
||||
----
|
||||
|
||||
Alternatively, if the {application-plugin}[`application` plugin] has been applied
|
||||
its `mainClassName` project property can be used:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/application-plugin-main-class.gradle[tags=main-class]
|
||||
----
|
||||
|
||||
Lastly, the `Start-Class` attribute can be configured on the task's manifest:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-manifest-main-class.gradle[tags=main-class]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-configuring-excluding-devtools]]
|
||||
==== Excluding Devtools
|
||||
|
||||
By default, Spring Boot's Devtools module,
|
||||
`org.springframework.boot:spring-boot-devtools`, will be excluded from an executable jar
|
||||
or war. If you want to include Devtools in your archive set the `excludeDevtools`
|
||||
property to `false`:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-war-include-devtools.gradle[tags=include-devtools]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-configuring-unpacking]]
|
||||
==== Configuring libraries that require unpacking
|
||||
|
||||
Most libraries can be used directly when nested in an executable archive, however certain
|
||||
libraries can have problems. For example, JRuby includes its own nested jar support which
|
||||
assumes that `jruby-complete.jar` is always directly available on the file system.
|
||||
|
||||
To deal with any problematic libraries, an executable archive can be configured to unpack
|
||||
specific nested jars to a temporary folder when the executable archive is run. Libraries
|
||||
can be identified as requiring unpacking using Ant-style patterns that match against
|
||||
the absolute path of the source jar file:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-requires-unpack.gradle[tags=requires-unpack]
|
||||
----
|
||||
|
||||
For more control a closure can also be used. The closure is passed a `FileTreeElement`
|
||||
and should return a `boolean` indicating whether or not unpacking is required.
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-configuring-launch-script]]
|
||||
==== Making an archive fully executable
|
||||
|
||||
Spring Boot provides support for fully executable archives. An archive is made fully
|
||||
executable by prepending a shell script that knows how to launch the application. On
|
||||
Unix-like platforms, this launch script allows the archive to be run directly like any
|
||||
other executable or to be installed as a service.
|
||||
|
||||
To use this feature, the inclusion of the launch script must be enabled:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-include-launch-script.gradle[tags=include-launch-script]
|
||||
----
|
||||
|
||||
This will add Spring Boot's default launch script to the archive. The default launch
|
||||
script includes several properties with sensible default values. The values can be
|
||||
customized using the `properties` property:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-launch-script-properties.gradle[tags=launch-script-properties]
|
||||
----
|
||||
|
||||
If the default launch script does not meet your needs, the `script` property can be used
|
||||
to provide a custom launch script:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-jar-custom-launch-script.gradle[tags=custom-launch-script]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[packaging-executable-configuring-properties-launcher]]
|
||||
==== Using the `PropertiesLauncher`
|
||||
|
||||
To use the `PropertiesLauncher` to launch an executable jar or war, configure the task's
|
||||
manifest to set the `Main-Class` attribute:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/packaging/boot-war-properties-launcher.gradle[tags=properties-launcher]
|
||||
----
|
||||
@@ -0,0 +1,41 @@
|
||||
[[publishing-your-application]]
|
||||
== Publishing your application
|
||||
|
||||
|
||||
|
||||
[[publishing-your-application-maven]]
|
||||
=== Publishing with the `maven` plugin
|
||||
|
||||
When the {maven-plugin}[`maven` plugin] is applied, an `Upload` task for the
|
||||
`bootArchives` configuration named `uploadBootArchives` is automatically created. By
|
||||
default, the `bootArchives` configuration contains the archive produced by the `bootJar`
|
||||
or `bootWar` task. The `uploadBootArchives` task can be configured to publish the archive
|
||||
to a Maven repository:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/publishing/maven.gradle[tags=upload]
|
||||
----
|
||||
|
||||
[[publishing-your-application-maven-publish]]
|
||||
=== Publishing with the `maven-publish` plugin
|
||||
|
||||
To publish your Spring Boot jar or war, add it to the publication using the `artifact`
|
||||
method on `MavenPublication`. Pass the task that produces that artifact that you wish
|
||||
to publish to the `artifact` method. For example, to publish the artifact produced by the
|
||||
default `bootJar` task:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/publishing/maven-publish.gradle[tags=publishing]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[publishing-your-application-distribution]]
|
||||
=== Distributing with the `application` plugin
|
||||
|
||||
When the {application-plugin}[`application` plugin] is applied a distribution named
|
||||
`boot` is created. This distribution contains the archive produced by the `bootJar` or
|
||||
`bootWar` task and scripts to launch it on Unix-like platforms and Windows. Zip and tar
|
||||
distributions can be built by the `bootDistZip` and `bootDistTar` tasks respectively.
|
||||
@@ -0,0 +1,79 @@
|
||||
[[reacting-to-other-plugins]]
|
||||
== Reacting to other plugins
|
||||
|
||||
When another plugin is applied the Spring Boot plugin reacts by making various changes
|
||||
to the project's configuration. This section describes those changes.
|
||||
|
||||
[[reacting-to-other-plugins-java]]
|
||||
=== Reacting to the Java plugin
|
||||
|
||||
When Gradle's {java-plugin}[`java` plugin] is applied to a project, the Spring Boot
|
||||
plugin:
|
||||
|
||||
1. Creates a {boot-jar-javadoc}[`BootJar`] task named `bootJar` that will create an
|
||||
executable, fat jar for the project. The jar will contain everything on the runtime
|
||||
classpath of the main source set; classes are packaged in `BOOT-INF/classes` and jars
|
||||
are packaged in `BOOT-INF/lib`
|
||||
2. Configures the `assemble` task to depend on the `bootJar` task.
|
||||
3. Disables the `jar` task.
|
||||
4. Creates a {boot-run-javadoc}[`BootRun`] task named `bootRun` that can be used to run
|
||||
your application.
|
||||
5. Creates a configuration named `bootArchives` that contains the artifact produced by
|
||||
the `bootJar` task.
|
||||
6. Configures any `JavaCompile` tasks with no configured encoding to use `UTF-8`.
|
||||
7. Configures any `JavaCompile` tasks to use the `-parameters` compiler argument.
|
||||
|
||||
|
||||
|
||||
[[reacting-to-other-plugins-war]]
|
||||
=== Reacting to the war plugin
|
||||
|
||||
When Gradle's {war-plugin}[`war` plugin] is applied to a project, the Spring Boot plugin:
|
||||
|
||||
1. Creates a {boot-war-javadoc}[`BootWar`] task named `bootWar` that will create an
|
||||
executable, fat war for the project. In addition to the standard packaging, everything
|
||||
in the `providedRuntime` configuration will be packaged in `WEB-INF/lib-provided`.
|
||||
2. Configures the `assemble` task to depend on the `bootWar` task.
|
||||
3. Disables the `war` task.
|
||||
4. Configures the `bootArchives` configuration to contain the artifact produced by the
|
||||
`bootWar` task.
|
||||
|
||||
|
||||
|
||||
[[reacting-to-other-plugins-dependency-management]]
|
||||
=== Reacting to the dependency management plugin
|
||||
|
||||
When the {dependency-management-plugin}[`io.spring.dependency-management` plugin] is
|
||||
applied to a project, the Spring Boot plugin will automatically import the
|
||||
`spring-boot-dependencies` bom.
|
||||
|
||||
|
||||
|
||||
[[reacting-to-other-plugins-application]]
|
||||
=== Reacting to the application plugin
|
||||
|
||||
When Gradle's {application-plugin}[`application` plugin] is applied to a project, the
|
||||
Spring Boot plugin:
|
||||
|
||||
1. Creates a `CreateStartScripts` task named `bootStartScripts` that will creates scripts
|
||||
that launch the artifact in the `bootArchives` configuration using `java -jar`.
|
||||
2. Creates a new distribution named `boot` and configures it to contain the artifact in
|
||||
the `bootArchives` configuration in its `lib` directory and the start scripts in its
|
||||
`bin` directory.
|
||||
3. Configures the `bootRun` task to use the `mainClassName` property as a convention for
|
||||
its `main` property.
|
||||
4. Configures the `bootRun` task to use the `applicationDefaultJvmArgs` property as a
|
||||
convention for its `jvmArgs` property.
|
||||
5. Configures the `bootJar` task to use the `mainClassName` property as a convention for
|
||||
the `Start-Class` entry in its manifest.
|
||||
6. Configures the `bootWar` task to use the `mainClassName` property as a convention for
|
||||
the `Start-Class` entry in its manifest.
|
||||
|
||||
|
||||
|
||||
[[reacting-to-other-plugins-maven]]
|
||||
=== Reacting to the Maven plugin
|
||||
|
||||
When Gradle's {maven-plugin}[`maven` plugin] is applied to a project, the Spring Boot
|
||||
plugin will configure the `uploadBootArchives` `Upload` task to ensure that no
|
||||
dependencies are declared in the pom that it generates.
|
||||
@@ -0,0 +1,53 @@
|
||||
[[running-your-application]]
|
||||
== Running your application with Gradle
|
||||
|
||||
To run your application without first building an archive use the `bootRun` task:
|
||||
|
||||
[source,bash,indent=0,subs="verbatim"]
|
||||
----
|
||||
$ ./gradlew bootRun
|
||||
----
|
||||
|
||||
The `bootRun` task is automatically configured to use the runtime classpath of the
|
||||
main source set. By default, the main class will be discovered by looking for a class
|
||||
with a `public static void main(String[])` method in directories on the task's
|
||||
classpath. The main class can also be configured explicitly using the task's `main`
|
||||
property:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/running/boot-run-main.gradle[tags=main]
|
||||
----
|
||||
|
||||
Alternatively, if the {application-plugin}[`application` plugin] has been applied
|
||||
its `mainClassName` project property can be used:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/running/application-plugin-main-class-name.gradle[tags=main-class]
|
||||
----
|
||||
|
||||
Two properties, `args` and `jvmArgs`, are also provided for configuring the
|
||||
arguments and JVM arguments that are used to run the application.
|
||||
|
||||
For more advanced configuration the `JavaExecSpec` that is used can be customized:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/running/boot-run-custom-exec-spec.gradle[tags=customization]
|
||||
----
|
||||
|
||||
|
||||
[[running-your-application-reloading-resources]]
|
||||
=== Reloading resources
|
||||
If devtools has been added to your project it will automatically monitor your
|
||||
application for changes. Alternatively, you can configure `bootRun` such that your
|
||||
application's static resources are loaded from their source location:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::../gradle/running/boot-run-source-resources.gradle[tags=source-resources]
|
||||
----
|
||||
|
||||
This makes them reloadable in the live application which can be helpful at development
|
||||
time.
|
||||
@@ -0,0 +1,11 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url 'https://repo.spring.io/libs-milestone' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'org.springframework.boot:spring-boot-gradle-plugin:{version}'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
@@ -0,0 +1,3 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '{version}'
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url 'https://repo.spring.io/libs-snapshot' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
@@ -0,0 +1,17 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
// tag::apply[]
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
// end::apply[]
|
||||
|
||||
task verify {
|
||||
doLast {
|
||||
plugins.getPlugin(org.gradle.api.plugins.JavaPlugin.class)
|
||||
plugins.getPlugin(io.spring.gradle.dependencymanagement.DependencyManagementPlugin.class)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::additional[]
|
||||
springBoot {
|
||||
buildInfo {
|
||||
properties {
|
||||
additional = [
|
||||
'a': 'alpha',
|
||||
'b': 'bravo'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::additional[]
|
||||
@@ -0,0 +1,14 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::build-info[]
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
// end::build-info[]
|
||||
@@ -0,0 +1,21 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::custom-values[]
|
||||
springBoot {
|
||||
buildInfo {
|
||||
properties {
|
||||
artifact = 'example-app'
|
||||
version = '1.2.3'
|
||||
group = 'com.example'
|
||||
name = 'Example application'
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::custom-values[]
|
||||
@@ -0,0 +1,32 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
dependencyManagement {
|
||||
resolutionStrategy {
|
||||
eachDependency {
|
||||
if (it.requested.group == 'org.springframework.boot') {
|
||||
it.useVersion project.bootVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tag::custom-version[]
|
||||
ext['slf4j.version'] = '1.7.20'
|
||||
// end::custom-version[]
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
task slf4jVersion {
|
||||
doLast {
|
||||
println dependencyManagement.managedVersions['org.slf4j:slf4j-api']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
// tag::dependencies[]
|
||||
dependencies {
|
||||
compile 'org.springframework.boot:spring-boot-starter-web'
|
||||
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
}
|
||||
// end::dependencies[]
|
||||
@@ -0,0 +1,13 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'application'
|
||||
|
||||
// tag::main-class[]
|
||||
mainClassName = 'com.example.ExampleApplication'
|
||||
// end::main-class[]
|
||||
@@ -0,0 +1,24 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::enable-jar[]
|
||||
jar {
|
||||
enabled = true
|
||||
}
|
||||
// end::enable-jar[]
|
||||
|
||||
// tag::classifier[]
|
||||
bootJar {
|
||||
classifier = 'boot'
|
||||
}
|
||||
// end::classifier[]
|
||||
|
||||
bootJar {
|
||||
mainClass = 'com.example.Application'
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
bootJar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::custom-launch-script[]
|
||||
bootJar {
|
||||
launchScript {
|
||||
script = file('src/custom.script')
|
||||
}
|
||||
}
|
||||
// end::custom-launch-script[]
|
||||
@@ -0,0 +1,18 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
bootJar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::include-launch-script[]
|
||||
bootJar {
|
||||
launchScript()
|
||||
}
|
||||
// end::include-launch-script[]
|
||||
@@ -0,0 +1,20 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
bootJar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::launch-script-properties[]
|
||||
bootJar {
|
||||
launchScript {
|
||||
properties 'logFilename': 'example-app.log'
|
||||
}
|
||||
}
|
||||
// end::launch-script-properties[]
|
||||
@@ -0,0 +1,14 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::main-class[]
|
||||
bootJar {
|
||||
mainClass = 'com.example.ExampleApplication'
|
||||
}
|
||||
// end::main-class[]
|
||||
@@ -0,0 +1,16 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::main-class[]
|
||||
bootJar {
|
||||
manifest {
|
||||
attributes 'Start-Class': 'com.example.ExampleApplication'
|
||||
}
|
||||
}
|
||||
// end::main-class[]
|
||||
@@ -0,0 +1,26 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
runtime 'org.jruby:jruby-complete:1.7.25'
|
||||
}
|
||||
|
||||
bootJar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::requires-unpack[]
|
||||
bootJar {
|
||||
requiresUnpack '**/jruby-complete-*.jar'
|
||||
}
|
||||
// end::requires-unpack[]
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'war'
|
||||
|
||||
bootWar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
classpath file('spring-boot-devtools-1.2.3.RELEASE.jar')
|
||||
}
|
||||
|
||||
// tag::include-devtools[]
|
||||
bootWar {
|
||||
excludeDevtools = false
|
||||
}
|
||||
// end::include-devtools[]
|
||||
@@ -0,0 +1,20 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'war'
|
||||
|
||||
bootWar {
|
||||
mainClass 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::properties-launcher[]
|
||||
bootWar {
|
||||
manifest {
|
||||
attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
|
||||
}
|
||||
}
|
||||
// end::properties-launcher[]
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'war'
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
// tag::dependencies[]
|
||||
dependencies {
|
||||
compile 'org.springframework.boot:spring-boot-starter-web'
|
||||
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
|
||||
}
|
||||
// end::dependencies[]
|
||||
@@ -0,0 +1,31 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
// tag::publishing[]
|
||||
publishing {
|
||||
publications {
|
||||
bootJava(MavenPublication) {
|
||||
artifact bootJar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://repo.example.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::publishing[]
|
||||
|
||||
task publishingConfiguration {
|
||||
doLast {
|
||||
println publishing.publications.bootJava
|
||||
println publishing.repositories.maven.url
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
|
||||
// tag::upload[]
|
||||
uploadBootArchives {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
repository url: 'https://repo.example.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::upload[]
|
||||
|
||||
task deployerRepository {
|
||||
doLast {
|
||||
println uploadBootArchives.repositories.mavenDeployer.repository.url
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'application'
|
||||
|
||||
// tag::main-class[]
|
||||
mainClassName = 'com.example.ExampleApplication'
|
||||
// end::main-class[]
|
||||
|
||||
task configuredMainClass {
|
||||
doLast {
|
||||
println bootRun.main
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::customization[]
|
||||
bootRun {
|
||||
execSpec {
|
||||
systemProperty 'com.example.foo', 'bar'
|
||||
}
|
||||
}
|
||||
// end::customization[]
|
||||
@@ -0,0 +1,20 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::main[]
|
||||
bootRun {
|
||||
main = 'com.example.ExampleApplication'
|
||||
}
|
||||
// end::main[]
|
||||
|
||||
task configuredMainClass {
|
||||
doLast {
|
||||
println bootRun.main
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
// tag::source-resources[]
|
||||
bootRun {
|
||||
sourceResources sourceSets.main
|
||||
}
|
||||
// end::source-resources[]
|
||||
|
||||
task configuredClasspath {
|
||||
doLast {
|
||||
println bootRun.classpath.files
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.dsl;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.jvm.tasks.Jar;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo;
|
||||
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfoProperties;
|
||||
|
||||
/**
|
||||
* Entry point to Spring Boot's Gradle DSL.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class SpringBootExtension {
|
||||
|
||||
private final Project project;
|
||||
|
||||
/**
|
||||
* Creates a new {@code SpringBootPluginExtension} that is associated with the given
|
||||
* {@code project}.
|
||||
*
|
||||
* @param project the project
|
||||
*/
|
||||
public SpringBootExtension(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BuildInfo} task named {@code bootBuildInfo} and configures the
|
||||
* Java plugin's {@code classes} task to depend upon it.
|
||||
* <p>
|
||||
* By default, the task's destination dir will be a directory named {@code META-INF}
|
||||
* beneath the main source set's resources output directory, and the task's project
|
||||
* artifact will be the base name of the {@code bootWar} or {@code bootJar} task.
|
||||
*/
|
||||
public void buildInfo() {
|
||||
this.buildInfo(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BuildInfo} task named {@code bootBuildInfo} and configures the
|
||||
* Java plugin's {@code classes} task to depend upon it. The task is passed to the
|
||||
* given {@code configurer} for further configuration.
|
||||
* <p>
|
||||
* By default, the task's destination dir will be a directory named {@code META-INF}
|
||||
* beneath the main source set's resources output directory, and the task's project
|
||||
* artifact will be the base name of the {@code bootWar} or {@code bootJar} task.
|
||||
*
|
||||
* @param configurer the task configurer
|
||||
*/
|
||||
public void buildInfo(Action<BuildInfo> configurer) {
|
||||
BuildInfo bootBuildInfo = this.project.getTasks().create("bootBuildInfo",
|
||||
BuildInfo.class);
|
||||
bootBuildInfo.setGroup(BasePlugin.BUILD_GROUP);
|
||||
bootBuildInfo.setDescription("Generates a META-INF/build-info.properties file.");
|
||||
this.project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
|
||||
this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
.dependsOn(bootBuildInfo);
|
||||
this.project.afterEvaluate((evaluated) -> {
|
||||
BuildInfoProperties properties = bootBuildInfo.getProperties();
|
||||
if (properties.getArtifact() == null) {
|
||||
properties.setArtifact(determineArtifactBaseName());
|
||||
}
|
||||
});
|
||||
bootBuildInfo.setDestinationDir(this.project
|
||||
.provider(() -> new File(determineMainSourceSetResourcesOutputDir(),
|
||||
"META-INF")));
|
||||
});
|
||||
if (configurer != null) {
|
||||
configurer.execute(bootBuildInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private File determineMainSourceSetResourcesOutputDir() {
|
||||
return this.project.getConvention().getPlugin(JavaPluginConvention.class)
|
||||
.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput()
|
||||
.getResourcesDir();
|
||||
}
|
||||
|
||||
private String determineArtifactBaseName() {
|
||||
Jar artifactTask = findArtifactTask();
|
||||
return (artifactTask == null ? null : artifactTask.getBaseName());
|
||||
}
|
||||
|
||||
private Jar findArtifactTask() {
|
||||
Jar artifactTask = (Jar) this.project.getTasks().findByName("bootWar");
|
||||
if (artifactTask != null) {
|
||||
return artifactTask;
|
||||
}
|
||||
return (Jar) this.project.getTasks().findByName("bootJar");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Boot Gradle DSL.
|
||||
*/
|
||||
package org.springframework.boot.gradle.dsl;
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.distribution.Distribution;
|
||||
import org.gradle.api.distribution.DistributionContainer;
|
||||
import org.gradle.api.file.CopySpec;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.plugins.ApplicationPlugin;
|
||||
import org.gradle.api.plugins.ApplicationPluginConvention;
|
||||
import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.application.CreateBootStartScripts;
|
||||
|
||||
/**
|
||||
* Action that is executed in response to the {@link ApplicationPlugin} being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class ApplicationPluginAction implements PluginApplicationAction {
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
ApplicationPluginConvention applicationConvention = project.getConvention()
|
||||
.getPlugin(ApplicationPluginConvention.class);
|
||||
DistributionContainer distributions = project.getExtensions()
|
||||
.getByType(DistributionContainer.class);
|
||||
Distribution distribution = distributions.create("boot");
|
||||
CreateBootStartScripts bootStartScripts = project.getTasks()
|
||||
.create("bootStartScripts", CreateBootStartScripts.class);
|
||||
bootStartScripts.setDescription("Generates OS-specific start scripts to run the"
|
||||
+ " project as a Spring Boot application.");
|
||||
((TemplateBasedScriptGenerator) bootStartScripts.getUnixStartScriptGenerator())
|
||||
.setTemplate(project.getResources().getText()
|
||||
.fromString(loadResource("/unixStartScript.txt")));
|
||||
((TemplateBasedScriptGenerator) bootStartScripts.getWindowsStartScriptGenerator())
|
||||
.setTemplate(project.getResources().getText()
|
||||
.fromString(loadResource("/windowsStartScript.txt")));
|
||||
project.getConfigurations().all((configuration) -> {
|
||||
if ("bootArchives".equals(configuration.getName())) {
|
||||
distribution.getContents()
|
||||
.with(project.copySpec().into("lib")
|
||||
.from((Callable<FileCollection>) () -> configuration
|
||||
.getArtifacts().getFiles()));
|
||||
bootStartScripts.setClasspath(configuration.getArtifacts().getFiles());
|
||||
}
|
||||
});
|
||||
bootStartScripts.setOutputDir(
|
||||
project.provider(() -> new File(project.getBuildDir(), "bootScripts")));
|
||||
bootStartScripts.setApplicationName(
|
||||
project.provider(() -> applicationConvention.getApplicationName()));
|
||||
CopySpec binCopySpec = project.copySpec().into("bin").from(bootStartScripts);
|
||||
binCopySpec.setFileMode(0x755);
|
||||
distribution.getContents().with(binCopySpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Plugin<Project>> getPluginClass() {
|
||||
return ApplicationPlugin.class;
|
||||
}
|
||||
|
||||
private String loadResource(String name) {
|
||||
try (InputStreamReader reader = new InputStreamReader(
|
||||
getClass().getResourceAsStream(name))) {
|
||||
char[] buffer = new char[4096];
|
||||
int read = 0;
|
||||
StringWriter writer = new StringWriter();
|
||||
while ((read = reader.read(buffer)) > 0) {
|
||||
writer.write(buffer, 0, read);
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new GradleException("Failed to read '" + name + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
|
||||
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* {@link Action} that is performed in response to the {@link DependencyManagementPlugin}
|
||||
* being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class DependencyManagementPluginAction implements PluginApplicationAction {
|
||||
|
||||
private static final String SPRING_BOOT_VERSION = determineSpringBootVersion();
|
||||
|
||||
private static final String SPRING_BOOT_BOM = "org.springframework.boot:spring-boot-dependencies:"
|
||||
+ SPRING_BOOT_VERSION;
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
project.getExtensions().findByType(DependencyManagementExtension.class)
|
||||
.imports((importsHandler) -> importsHandler.mavenBom(SPRING_BOOT_BOM));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Plugin<Project>> getPluginClass() {
|
||||
return DependencyManagementPlugin.class;
|
||||
}
|
||||
|
||||
private static String determineSpringBootVersion() {
|
||||
String implementationVersion = DependencyManagementPluginAction.class.getPackage()
|
||||
.getImplementationVersion();
|
||||
if (implementationVersion != null) {
|
||||
return implementationVersion;
|
||||
}
|
||||
URL codeSourceLocation = DependencyManagementPluginAction.class
|
||||
.getProtectionDomain().getCodeSource().getLocation();
|
||||
try {
|
||||
URLConnection connection = codeSourceLocation.openConnection();
|
||||
if (connection instanceof JarURLConnection) {
|
||||
return getImplementationVersion(
|
||||
((JarURLConnection) connection).getJarFile());
|
||||
}
|
||||
try (JarFile jarFile = new JarFile(new File(codeSourceLocation.toURI()))) {
|
||||
return getImplementationVersion(jarFile);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getImplementationVersion(JarFile jarFile) throws IOException {
|
||||
return jarFile.getManifest().getMainAttributes()
|
||||
.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact;
|
||||
import org.gradle.api.plugins.ApplicationPlugin;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootJar;
|
||||
import org.springframework.boot.gradle.tasks.run.BootRun;
|
||||
|
||||
/**
|
||||
* {@link Action} that is executed in response to the {@link JavaPlugin} being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class JavaPluginAction implements PluginApplicationAction {
|
||||
|
||||
private static final String PARAMETERS_COMPILER_ARG = "-parameters";
|
||||
private final SinglePublishedArtifact singlePublishedArtifact;
|
||||
|
||||
JavaPluginAction(SinglePublishedArtifact singlePublishedArtifact) {
|
||||
this.singlePublishedArtifact = singlePublishedArtifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Plugin<? extends Project>> getPluginClass() {
|
||||
return JavaPlugin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
disableJarTask(project);
|
||||
configureBuildTask(project);
|
||||
BootJar bootJar = configureBootJarTask(project);
|
||||
configureArtifactPublication(project, bootJar);
|
||||
configureBootRunTask(project);
|
||||
configureUtf8Encoding(project);
|
||||
configureParametersCompilerArg(project);
|
||||
}
|
||||
|
||||
private void disableJarTask(Project project) {
|
||||
project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME).setEnabled(false);
|
||||
}
|
||||
|
||||
private void configureBuildTask(Project project) {
|
||||
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME)
|
||||
.dependsOn(this.singlePublishedArtifact);
|
||||
}
|
||||
|
||||
private BootJar configureBootJarTask(Project project) {
|
||||
BootJar bootJar = project.getTasks().create(SpringBootPlugin.BOOT_JAR_TASK_NAME,
|
||||
BootJar.class);
|
||||
bootJar.setDescription("Assembles an executable jar archive containing the main"
|
||||
+ " classes and their dependencies.");
|
||||
bootJar.setGroup(BasePlugin.BUILD_GROUP);
|
||||
bootJar.classpath((Callable<FileCollection>) () -> {
|
||||
JavaPluginConvention convention = project.getConvention()
|
||||
.getPlugin(JavaPluginConvention.class);
|
||||
SourceSet mainSourceSet = convention.getSourceSets()
|
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
return mainSourceSet.getRuntimeClasspath();
|
||||
});
|
||||
bootJar.conventionMapping("mainClass",
|
||||
new MainClassConvention(project, bootJar::getClasspath));
|
||||
return bootJar;
|
||||
}
|
||||
|
||||
private void configureArtifactPublication(Project project, BootJar bootJar) {
|
||||
ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootJar);
|
||||
this.singlePublishedArtifact.addCandidate(artifact);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void configureBootRunTask(Project project) {
|
||||
JavaPluginConvention javaConvention = project.getConvention()
|
||||
.getPlugin(JavaPluginConvention.class);
|
||||
BootRun run = project.getTasks().create("bootRun", BootRun.class);
|
||||
run.setDescription("Runs this project as a Spring Boot application.");
|
||||
run.setGroup(ApplicationPlugin.APPLICATION_GROUP);
|
||||
run.classpath(javaConvention.getSourceSets()
|
||||
.findByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath());
|
||||
run.setJvmArgs(project.provider(() -> {
|
||||
if (project.hasProperty("applicationDefaultJvmArgs")) {
|
||||
return (List<String>) project.property("applicationDefaultJvmArgs");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}));
|
||||
run.setMain(
|
||||
project.provider(new MainClassConvention(project, run::getClasspath)));
|
||||
}
|
||||
|
||||
private void configureUtf8Encoding(Project project) {
|
||||
project.afterEvaluate((evaluated) -> evaluated.getTasks()
|
||||
.withType(JavaCompile.class, (compile) -> {
|
||||
if (compile.getOptions().getEncoding() == null) {
|
||||
compile.getOptions().setEncoding("UTF-8");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void configureParametersCompilerArg(Project project) {
|
||||
project.getTasks().withType(JavaCompile.class, (compile) -> {
|
||||
List<String> compilerArgs = compile.getOptions().getCompilerArgs();
|
||||
if (!compilerArgs.contains(PARAMETERS_COMPILER_ARG)) {
|
||||
compilerArgs.add(PARAMETERS_COMPILER_ARG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
* A {@link Callable} that provides a convention for the project's main class name.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class MainClassConvention implements Callable<String> {
|
||||
|
||||
private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";
|
||||
|
||||
private final Project project;
|
||||
|
||||
private final Supplier<FileCollection> classpathSupplier;
|
||||
|
||||
MainClassConvention(Project project, Supplier<FileCollection> classpathSupplier) {
|
||||
this.project = project;
|
||||
this.classpathSupplier = classpathSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (this.project.hasProperty("mainClassName")) {
|
||||
Object mainClassName = this.project.property("mainClassName");
|
||||
if (mainClassName != null) {
|
||||
return mainClassName.toString();
|
||||
}
|
||||
}
|
||||
return resolveMainClass();
|
||||
}
|
||||
|
||||
private String resolveMainClass() {
|
||||
return this.classpathSupplier.get().filter(File::isDirectory).getFiles().stream()
|
||||
.map(this::findMainClass).filter(Objects::nonNull).findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private String findMainClass(File file) {
|
||||
try {
|
||||
return MainClassFinder.findSingleMainClass(file,
|
||||
SPRING_BOOT_APPLICATION_CLASS_NAME);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.maven.MavenResolver;
|
||||
import org.gradle.api.plugins.MavenPlugin;
|
||||
import org.gradle.api.tasks.Upload;
|
||||
|
||||
/**
|
||||
* {@link Action} that is executed in response to the {@link MavenPlugin} being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class MavenPluginAction implements PluginApplicationAction {
|
||||
|
||||
private final String uploadTaskName;
|
||||
|
||||
MavenPluginAction(String uploadTaskName) {
|
||||
this.uploadTaskName = uploadTaskName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Plugin<? extends Project>> getPluginClass() {
|
||||
return MavenPlugin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
project.getTasks().withType(Upload.class, (upload) -> {
|
||||
if (this.uploadTaskName.equals(upload.getName())) {
|
||||
project.afterEvaluate((evaluated) -> clearConfigurationMappings(upload));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearConfigurationMappings(Upload upload) {
|
||||
upload.getRepositories().withType(MavenResolver.class,
|
||||
(resolver) -> resolver.getPom().getScopeMappings().getMappings().clear());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* An {@link Action} to be executed on a {@link Project} in response to a particular type
|
||||
* of {@link Plugin} being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
interface PluginApplicationAction extends Action<Project> {
|
||||
|
||||
/**
|
||||
* The class of the {@code Plugin} that, when applied, will trigger the execution of
|
||||
* this action.
|
||||
*
|
||||
* @return the plugin class
|
||||
*/
|
||||
Class<? extends Plugin<? extends Project>> getPluginClass();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.gradle.api.Buildable;
|
||||
import org.gradle.api.artifacts.PublishArtifact;
|
||||
import org.gradle.api.artifacts.PublishArtifactSet;
|
||||
import org.gradle.api.tasks.TaskDependency;
|
||||
|
||||
/**
|
||||
* A wrapper for a {@PublishArtifactSet} that ensures that only a single artifact is
|
||||
* published, with a war file taking precedence over a jar file.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class SinglePublishedArtifact implements Buildable {
|
||||
|
||||
private final PublishArtifactSet artifacts;
|
||||
|
||||
private PublishArtifact currentArtifact;
|
||||
|
||||
SinglePublishedArtifact(PublishArtifactSet artifacts) {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
void addCandidate(PublishArtifact candidate) {
|
||||
if (this.currentArtifact == null || "war".equals(candidate.getExtension())) {
|
||||
this.artifacts.remove(this.currentArtifact);
|
||||
this.artifacts.add(candidate);
|
||||
this.currentArtifact = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskDependency getBuildDependencies() {
|
||||
return this.currentArtifact.getBuildDependencies();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.util.GradleVersion;
|
||||
|
||||
import org.springframework.boot.gradle.dsl.SpringBootExtension;
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootJar;
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootWar;
|
||||
|
||||
/**
|
||||
* Gradle plugin for Spring Boot.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class SpringBootPlugin implements Plugin<Project> {
|
||||
|
||||
/**
|
||||
* The name of the {@link Configuration} that contains Spring Boot archives.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static final String BOOT_ARCHIVES_CONFIGURATION_NAME = "bootArchives";
|
||||
|
||||
/**
|
||||
* The name of the default {@link BootJar} task.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static final String BOOT_JAR_TASK_NAME = "bootJar";
|
||||
|
||||
/**
|
||||
* The name of the default {@link BootWar} task.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static final String BOOT_WAR_TASK_NAME = "bootWar";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
verifyGradleVersion();
|
||||
createExtension(project);
|
||||
Configuration bootArchives = createBootArchivesConfiguration(project);
|
||||
registerPluginActions(project, bootArchives);
|
||||
unregisterUnresolvedDependenciesAnalyzer(project);
|
||||
}
|
||||
|
||||
private void verifyGradleVersion() {
|
||||
if (GradleVersion.current().compareTo(GradleVersion.version("4.0")) < 0) {
|
||||
throw new GradleException("Spring Boot plugin requires Gradle 4.0 or later."
|
||||
+ " The current version is " + GradleVersion.current());
|
||||
}
|
||||
}
|
||||
|
||||
private void createExtension(Project project) {
|
||||
project.getExtensions().create("springBoot", SpringBootExtension.class, project);
|
||||
}
|
||||
|
||||
private Configuration createBootArchivesConfiguration(Project project) {
|
||||
Configuration bootArchives = project.getConfigurations()
|
||||
.create(BOOT_ARCHIVES_CONFIGURATION_NAME);
|
||||
bootArchives.setDescription("Configuration for Spring Boot archive artifacts.");
|
||||
return bootArchives;
|
||||
}
|
||||
|
||||
private void registerPluginActions(Project project, Configuration bootArchives) {
|
||||
SinglePublishedArtifact singlePublishedArtifact = new SinglePublishedArtifact(
|
||||
bootArchives.getArtifacts());
|
||||
List<PluginApplicationAction> actions = Arrays.asList(
|
||||
new JavaPluginAction(singlePublishedArtifact),
|
||||
new WarPluginAction(singlePublishedArtifact),
|
||||
new MavenPluginAction(bootArchives.getUploadTaskName()),
|
||||
new DependencyManagementPluginAction(), new ApplicationPluginAction());
|
||||
for (PluginApplicationAction action : actions) {
|
||||
project.getPlugins().withType(action.getPluginClass(),
|
||||
(plugin) -> action.execute(project));
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterUnresolvedDependenciesAnalyzer(Project project) {
|
||||
UnresolvedDependenciesAnalyzer unresolvedDependenciesAnalyzer = new UnresolvedDependenciesAnalyzer();
|
||||
project.getConfigurations().all((configuration) -> configuration.getIncoming()
|
||||
.afterResolve((resolvableDependencies) -> unresolvedDependenciesAnalyzer
|
||||
.analyze(configuration.getResolvedConfiguration()
|
||||
.getLenientConfiguration()
|
||||
.getUnresolvedModuleDependencies())));
|
||||
project.getGradle().buildFinished(
|
||||
(buildResult) -> unresolvedDependenciesAnalyzer.buildFinished(project));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.ModuleVersionSelector;
|
||||
import org.gradle.api.artifacts.UnresolvedDependency;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An analyzer for {@link UnresolvedDependency unresolvable dependencies} that logs a
|
||||
* warning suggesting that the {@code io.spring.dependency-management} plugin is applied
|
||||
* when one or more versionless dependencies fails to resolve.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class UnresolvedDependenciesAnalyzer {
|
||||
|
||||
private static final org.slf4j.Logger logger = LoggerFactory
|
||||
.getLogger(SpringBootPlugin.class);
|
||||
|
||||
private Set<ModuleVersionSelector> dependenciesWithNoVersion = new HashSet<>();
|
||||
|
||||
void analyze(Set<UnresolvedDependency> unresolvedDependencies) {
|
||||
this.dependenciesWithNoVersion = unresolvedDependencies.stream()
|
||||
.map((unresolvedDependency) -> unresolvedDependency.getSelector())
|
||||
.filter(this::hasNoVersion).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
void buildFinished(Project project) {
|
||||
if (!this.dependenciesWithNoVersion.isEmpty()
|
||||
&& !project.getPlugins().hasPlugin(DependencyManagementPlugin.class)) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("\nDuring the build, one or more dependencies that were "
|
||||
+ "declared without a version failed to resolve:\n");
|
||||
this.dependenciesWithNoVersion.stream()
|
||||
.forEach((dependency) -> message.append(" " + dependency + "\n"));
|
||||
message.append("\nDid you forget to apply the "
|
||||
+ "io.spring.dependency-management plugin to the " + project.getName()
|
||||
+ " project?\n");
|
||||
logger.warn(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNoVersion(ModuleVersionSelector selector) {
|
||||
String version = selector.getVersion();
|
||||
return version == null || version.trim().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.WarPlugin;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootWar;
|
||||
|
||||
/**
|
||||
* {@link Action} that is executed in response to the {@link WarPlugin} being applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class WarPluginAction implements PluginApplicationAction {
|
||||
|
||||
private final SinglePublishedArtifact singlePublishedArtifact;
|
||||
|
||||
WarPluginAction(SinglePublishedArtifact singlePublishedArtifact) {
|
||||
this.singlePublishedArtifact = singlePublishedArtifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Plugin<? extends Project>> getPluginClass() {
|
||||
return WarPlugin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
project.getTasks().getByName(WarPlugin.WAR_TASK_NAME).setEnabled(false);
|
||||
BootWar bootWar = project.getTasks().create(SpringBootPlugin.BOOT_WAR_TASK_NAME,
|
||||
BootWar.class);
|
||||
bootWar.setGroup(BasePlugin.BUILD_GROUP);
|
||||
bootWar.setDescription("Assembles an executable war archive containing webapp"
|
||||
+ " content, and the main classes and their dependencies.");
|
||||
bootWar.providedClasspath(providedRuntimeConfiguration(project));
|
||||
ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootWar);
|
||||
this.singlePublishedArtifact.addCandidate(artifact);
|
||||
bootWar.conventionMapping("mainClass",
|
||||
new MainClassConvention(project, bootWar::getClasspath));
|
||||
}
|
||||
|
||||
private Configuration providedRuntimeConfiguration(Project project) {
|
||||
return project.getConfigurations()
|
||||
.getByName(WarPlugin.PROVIDED_RUNTIME_CONFIGURATION_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Central classes for the Spring Boot Gradle plugin.
|
||||
*/
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.application;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.api.provider.PropertyState;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.jvm.application.tasks.CreateStartScripts;
|
||||
|
||||
/**
|
||||
* Customization of {@link CreateStartScripts} that makes the {@link #getMainClassName()
|
||||
* main class name} optional.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class CreateBootStartScripts extends CreateStartScripts {
|
||||
|
||||
private final PropertyState<File> outputDir = getProject().property(File.class);
|
||||
|
||||
private final PropertyState<String> applicationName = getProject()
|
||||
.property(String.class);
|
||||
|
||||
@Override
|
||||
@Optional
|
||||
public String getMainClassName() {
|
||||
return super.getMainClassName();
|
||||
}
|
||||
|
||||
@Input
|
||||
@Override
|
||||
public String getApplicationName() {
|
||||
return this.applicationName.getOrNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName.set(applicationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application name to the value from the given
|
||||
* {@code applicationNameProvider}.
|
||||
* @param applicationNameProvider the provider of the application name
|
||||
*/
|
||||
public void setApplicationName(Provider<String> applicationNameProvider) {
|
||||
this.applicationName.set(applicationNameProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@OutputDirectory
|
||||
public File getOutputDir() {
|
||||
return this.outputDir.getOrNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutputDir(File outputDir) {
|
||||
this.outputDir.set(outputDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output directory to the value from the given {@code outputDirProvider}.
|
||||
* @param outputDirProvider the provider of the output directory
|
||||
*/
|
||||
public void setOutputDir(Provider<File> outputDirProvider) {
|
||||
this.outputDir.set(outputDirProvider);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes related to Gradle's application features.
|
||||
*/
|
||||
package org.springframework.boot.gradle.tasks.application;
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.internal.ConventionTask;
|
||||
import org.gradle.api.provider.PropertyState;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.TaskExecutionException;
|
||||
|
||||
import org.springframework.boot.loader.tools.BuildPropertiesWriter;
|
||||
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
|
||||
|
||||
/**
|
||||
* {@link Task} for generating a {@code build-info.properties} file from a
|
||||
* {@code Project}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BuildInfo extends ConventionTask {
|
||||
|
||||
private final BuildInfoProperties properties = new BuildInfoProperties(getProject());
|
||||
|
||||
private PropertyState<File> destinationDir = getProject().property(File.class);
|
||||
|
||||
/**
|
||||
* Generates the {@code build-info.properties} file in the configured
|
||||
* {@link #setDestinationDir(File) destination}.
|
||||
*/
|
||||
@TaskAction
|
||||
public void generateBuildProperties() {
|
||||
try {
|
||||
new BuildPropertiesWriter(
|
||||
new File(getDestinationDir(), "build-info.properties"))
|
||||
.writeBuildProperties(new ProjectDetails(
|
||||
this.properties.getGroup(),
|
||||
this.properties.getArtifact() == null ? "unspecified"
|
||||
: this.properties.getArtifact(),
|
||||
this.properties.getVersion(),
|
||||
this.properties.getName(), coerceToStringValues(
|
||||
this.properties.getAdditional())));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new TaskExecutionException(this, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory to which the {@code build-info.properties} file will be
|
||||
* written. Defaults to the {@link Project#getBuildDir() Project's build directory}.
|
||||
*
|
||||
* @return the destination directory
|
||||
*/
|
||||
@OutputDirectory
|
||||
public File getDestinationDir() {
|
||||
return this.destinationDir.isPresent() ? this.destinationDir.get()
|
||||
: getProject().getBuildDir();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory to which the {@code build-info.properties} file will be written.
|
||||
* @param destinationDir the destination directory
|
||||
*/
|
||||
public void setDestinationDir(File destinationDir) {
|
||||
this.destinationDir.set(destinationDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory to which the {@code build-info.properties} file will be written
|
||||
* to the value from the given {@code destinationDirProvider}.
|
||||
* @param destinationDirProvider the provider of the destination directory
|
||||
*/
|
||||
public void setDestinationDir(Provider<File> destinationDirProvider) {
|
||||
this.destinationDir.set(destinationDirProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link BuildInfoProperties properties} that will be included in the
|
||||
* {@code build-info.properties} file.
|
||||
* @return the properties
|
||||
*/
|
||||
@Input
|
||||
public BuildInfoProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@code action} on the {@link #getProperties()} properties.
|
||||
* @param action the action
|
||||
*/
|
||||
public void properties(Action<BuildInfoProperties> action) {
|
||||
action.execute(this.properties);
|
||||
}
|
||||
|
||||
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
||||
Map<String, String> output = new HashMap<>();
|
||||
for (Entry<String, Object> entry : input.entrySet()) {
|
||||
output.put(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* The properties that are written into the {@code build-info.properties} file.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BuildInfoProperties implements Serializable {
|
||||
|
||||
private final transient Project project;
|
||||
|
||||
private String group;
|
||||
|
||||
private String artifact;
|
||||
|
||||
private String version;
|
||||
|
||||
private String name;
|
||||
|
||||
private Map<String, Object> additionalProperties = new HashMap<>();
|
||||
|
||||
BuildInfoProperties(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.group} property. Defaults to the
|
||||
* {@link Project#getGroup() Project's group}.
|
||||
*
|
||||
* @return the group
|
||||
*/
|
||||
public String getGroup() {
|
||||
return this.group != null ? this.group : this.project.getGroup().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.group} property.
|
||||
*
|
||||
* @param group the group name
|
||||
*/
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.artifact} property.
|
||||
*
|
||||
* @return the artifact
|
||||
*/
|
||||
public String getArtifact() {
|
||||
return this.artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.artifact} property.
|
||||
*
|
||||
* @param artifact the artifact
|
||||
*/
|
||||
public void setArtifact(String artifact) {
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.version} property. Defaults to the
|
||||
* {@link Project#getVersion() Project's version}.
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return this.version != null ? this.version : this.project.getVersion().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.version} property.
|
||||
*
|
||||
* @param version the version
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.name} property. Defaults to the
|
||||
* {@link Project#getDisplayName() Project's display name}.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name != null ? this.name : this.project.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.name} property.
|
||||
*
|
||||
* @param name the name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the additional properties that will be included. When written, the name of
|
||||
* each additional property is prefixed with {@code build.}.
|
||||
*
|
||||
* @return the additional properties
|
||||
*/
|
||||
public Map<String, Object> getAdditional() {
|
||||
return this.additionalProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the additional properties that will be included. When written, the name of
|
||||
* each additional property is prefixed with {@code build.}.
|
||||
*
|
||||
* @param additionalProperties the additional properties
|
||||
*/
|
||||
public void setAdditional(Map<String, Object> additionalProperties) {
|
||||
this.additionalProperties = additionalProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.additionalProperties == null) ? 0
|
||||
: this.additionalProperties.hashCode());
|
||||
result = prime * result
|
||||
+ ((this.artifact == null) ? 0 : this.artifact.hashCode());
|
||||
result = prime * result + ((this.group == null) ? 0 : this.group.hashCode());
|
||||
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
|
||||
result = prime * result + ((this.version == null) ? 0 : this.version.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BuildInfoProperties other = (BuildInfoProperties) obj;
|
||||
if (this.additionalProperties == null) {
|
||||
if (other.additionalProperties != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.additionalProperties.equals(other.additionalProperties)) {
|
||||
return false;
|
||||
}
|
||||
if (this.artifact == null) {
|
||||
if (other.artifact != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.artifact.equals(other.artifact)) {
|
||||
return false;
|
||||
}
|
||||
if (this.group == null) {
|
||||
if (other.group != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.group.equals(other.group)) {
|
||||
return false;
|
||||
}
|
||||
if (this.name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
if (this.version == null) {
|
||||
if (other.version != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.version.equals(other.version)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for producing build info for consumption by Spring Boot's actuator.
|
||||
*/
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
|
||||
/**
|
||||
* A Spring Boot "fat" archive task.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface BootArchive extends Task {
|
||||
|
||||
/**
|
||||
* Returns the main class of the application.
|
||||
*
|
||||
* @return the main class
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
String getMainClass();
|
||||
|
||||
/**
|
||||
* Sets the main class of the application.
|
||||
*
|
||||
* @param mainClass the main class of the application
|
||||
*/
|
||||
void setMainClass(String mainClass);
|
||||
|
||||
/**
|
||||
* Adds Ant-style patterns that identify files that must be unpacked from the archive
|
||||
* when it is launched.
|
||||
*
|
||||
* @param patterns the patterns
|
||||
*/
|
||||
void requiresUnpack(String... patterns);
|
||||
|
||||
/**
|
||||
* Adds a spec that identifies files that must be unpacked from the archive when it is
|
||||
* launched.
|
||||
*
|
||||
* @param spec the spec
|
||||
*/
|
||||
void requiresUnpack(Spec<FileTreeElement> spec);
|
||||
|
||||
/**
|
||||
* Returns the {@link LaunchScriptConfiguration} that will control the script that is
|
||||
* prepended to the archive.
|
||||
*
|
||||
* @return the launch script configuration, or {@code null} if the launch script has
|
||||
* not been configured.
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
LaunchScriptConfiguration getLaunchScript();
|
||||
|
||||
/**
|
||||
* Configures the archive to have a prepended launch script.
|
||||
*/
|
||||
void launchScript();
|
||||
|
||||
/**
|
||||
* Configures the archive to have a prepended launch script, customizing its
|
||||
* configuration using the given {@code action}.
|
||||
*
|
||||
* @param action the action to apply
|
||||
*/
|
||||
void launchScript(Action<LaunchScriptConfiguration> action);
|
||||
|
||||
/**
|
||||
* Returns the classpath that will be included in the archive.
|
||||
*
|
||||
* @return the classpath
|
||||
*/
|
||||
@Optional
|
||||
@Classpath
|
||||
FileCollection getClasspath();
|
||||
|
||||
/**
|
||||
* Adds files to the classpath to include in the archive. The given {@code classpath}
|
||||
* are evaluated as per {@link Project#files(Object...)}.
|
||||
*
|
||||
* @param classpath the additions to the classpath
|
||||
*/
|
||||
void classpath(Object... classpath);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the Devtools jar should be excluded, otherwise
|
||||
* {@code false}.
|
||||
*
|
||||
* @return {@code true} if the Devtools jar should be excluded, or {@code false} if
|
||||
* not
|
||||
*/
|
||||
@Input
|
||||
boolean isExcludeDevtools();
|
||||
|
||||
/**
|
||||
* Sets whether or not the Devtools jar should be excluded.
|
||||
*
|
||||
* @param excludeDevtools {@code true} if the Devtools jar should be excluded, or
|
||||
* {@code false} if not
|
||||
*/
|
||||
void setExcludeDevtools(boolean excludeDevtools);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.file.RelativePath;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
|
||||
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
|
||||
import org.gradle.api.java.archives.Attributes;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.specs.Specs;
|
||||
import org.gradle.api.tasks.WorkResult;
|
||||
import org.gradle.api.tasks.bundling.Jar;
|
||||
import org.gradle.api.tasks.util.PatternSet;
|
||||
|
||||
/**
|
||||
* Support class for implementations of {@link BootArchive}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class BootArchiveSupport {
|
||||
|
||||
private static final Set<String> DEFAULT_LAUNCHER_CLASSES;
|
||||
|
||||
static {
|
||||
Set<String> defaultLauncherClasses = new HashSet<>();
|
||||
defaultLauncherClasses.add("org.springframework.boot.loader.JarLauncher");
|
||||
defaultLauncherClasses.add("org.springframework.boot.loader.PropertiesLauncher");
|
||||
defaultLauncherClasses.add("org.springframework.boot.loader.WarLauncher");
|
||||
DEFAULT_LAUNCHER_CLASSES = Collections.unmodifiableSet(defaultLauncherClasses);
|
||||
}
|
||||
|
||||
private final PatternSet requiresUnpack = new PatternSet();
|
||||
|
||||
private final Function<FileCopyDetails, ZipCompression> compressionResolver;
|
||||
|
||||
private final PatternSet exclusions = new PatternSet();
|
||||
|
||||
private final String loaderMainClass;
|
||||
|
||||
private LaunchScriptConfiguration launchScript;
|
||||
|
||||
private boolean excludeDevtools = true;
|
||||
|
||||
BootArchiveSupport(String loaderMainClass,
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver) {
|
||||
this.loaderMainClass = loaderMainClass;
|
||||
this.compressionResolver = compressionResolver;
|
||||
this.requiresUnpack.include(Specs.satisfyNone());
|
||||
configureExclusions();
|
||||
}
|
||||
|
||||
void configureManifest(Jar jar, String mainClass) {
|
||||
Attributes attributes = jar.getManifest().getAttributes();
|
||||
attributes.putIfAbsent("Main-Class", this.loaderMainClass);
|
||||
attributes.putIfAbsent("Start-Class", mainClass);
|
||||
}
|
||||
|
||||
CopyAction createCopyAction(Jar jar) {
|
||||
CopyAction copyAction = new BootZipCopyAction(jar.getArchivePath(),
|
||||
jar.isPreserveFileTimestamps(), isUsingDefaultLoader(jar),
|
||||
this.requiresUnpack.getAsSpec(), this.exclusions.getAsExcludeSpec(),
|
||||
this.launchScript, this.compressionResolver, jar.getMetadataCharset());
|
||||
if (!jar.isReproducibleFileOrder()) {
|
||||
return copyAction;
|
||||
}
|
||||
return new ReproducibleOrderingCopyAction(copyAction);
|
||||
}
|
||||
|
||||
private boolean isUsingDefaultLoader(Jar jar) {
|
||||
return DEFAULT_LAUNCHER_CLASSES
|
||||
.contains(jar.getManifest().getAttributes().get("Main-Class"));
|
||||
}
|
||||
|
||||
LaunchScriptConfiguration getLaunchScript() {
|
||||
return this.launchScript;
|
||||
}
|
||||
|
||||
void setLaunchScript(LaunchScriptConfiguration launchScript) {
|
||||
this.launchScript = launchScript;
|
||||
}
|
||||
|
||||
void requiresUnpack(String... patterns) {
|
||||
this.requiresUnpack.include(patterns);
|
||||
}
|
||||
|
||||
void requiresUnpack(Spec<FileTreeElement> spec) {
|
||||
this.requiresUnpack.include(spec);
|
||||
}
|
||||
|
||||
boolean isExcludeDevtools() {
|
||||
return this.excludeDevtools;
|
||||
}
|
||||
|
||||
void setExcludeDevtools(boolean excludeDevtools) {
|
||||
this.excludeDevtools = excludeDevtools;
|
||||
configureExclusions();
|
||||
}
|
||||
|
||||
private void configureExclusions() {
|
||||
Set<String> excludes = new HashSet<>();
|
||||
if (this.excludeDevtools) {
|
||||
excludes.add("**/spring-boot-devtools-*.jar");
|
||||
}
|
||||
this.exclusions.setExcludes(excludes);
|
||||
}
|
||||
|
||||
private static final class ReproducibleOrderingCopyAction implements CopyAction {
|
||||
|
||||
private final CopyAction delegate;
|
||||
|
||||
private ReproducibleOrderingCopyAction(CopyAction delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkResult execute(CopyActionProcessingStream stream) {
|
||||
return this.delegate.execute((action) -> {
|
||||
Map<RelativePath, FileCopyDetailsInternal> detailsByPath = new TreeMap<>();
|
||||
stream.process((details) -> detailsByPath.put(details.getRelativePath(),
|
||||
details));
|
||||
detailsByPath.values().stream().forEach(action::processFile);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.file.CopySpec;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.bundling.Jar;
|
||||
|
||||
/**
|
||||
* A custom {@link Jar} task that produces a Spring Boot executable jar.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class BootJar extends Jar implements BootArchive {
|
||||
|
||||
private BootArchiveSupport support = new BootArchiveSupport(
|
||||
"org.springframework.boot.loader.JarLauncher", this::resolveZipCompression);
|
||||
|
||||
private FileCollection classpath;
|
||||
|
||||
private String mainClass;
|
||||
|
||||
/**
|
||||
* Creates a new {@code BootJar} task.
|
||||
*/
|
||||
public BootJar() {
|
||||
CopySpec bootInf = getRootSpec().addChildBeforeSpec(getMainSpec())
|
||||
.into("BOOT-INF");
|
||||
bootInf.into("lib", classpathFiles(File::isFile));
|
||||
bootInf.into("classes", classpathFiles(File::isDirectory));
|
||||
}
|
||||
|
||||
private Action<CopySpec> classpathFiles(Spec<File> filter) {
|
||||
return (copySpec) -> copySpec
|
||||
.from((Callable<Iterable<File>>) () -> this.classpath == null
|
||||
? Collections.emptyList() : this.classpath.filter(filter));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy() {
|
||||
this.support.configureManifest(this, getMainClass());
|
||||
super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CopyAction createCopyAction() {
|
||||
return this.support.createCopyAction(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMainClass() {
|
||||
return this.mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainClass(String mainClass) {
|
||||
this.mainClass = mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(String... patterns) {
|
||||
this.support.requiresUnpack(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(Spec<FileTreeElement> spec) {
|
||||
this.support.requiresUnpack(spec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LaunchScriptConfiguration getLaunchScript() {
|
||||
return this.support.getLaunchScript();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchScript() {
|
||||
enableLaunchScriptIfNecessary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchScript(Action<LaunchScriptConfiguration> action) {
|
||||
action.execute(enableLaunchScriptIfNecessary());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileCollection getClasspath() {
|
||||
return this.classpath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classpath(Object... classpath) {
|
||||
FileCollection existingClasspath = this.classpath;
|
||||
this.classpath = getProject().files(
|
||||
existingClasspath == null ? Collections.emptyList() : existingClasspath,
|
||||
classpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExcludeDevtools() {
|
||||
return this.support.isExcludeDevtools();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExcludeDevtools(boolean excludeDevtools) {
|
||||
this.support.setExcludeDevtools(excludeDevtools);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ZipCompression} that should be used when adding the file
|
||||
* represented by the given {@code details} to the jar.
|
||||
* <p>
|
||||
* By default, any file in {@code BOOT-INF/lib/} is stored and all other files are
|
||||
* deflated.
|
||||
*
|
||||
* @param details the details
|
||||
* @return the compression to use
|
||||
*/
|
||||
protected ZipCompression resolveZipCompression(FileCopyDetails details) {
|
||||
if (details.getRelativePath().getPathString().startsWith("BOOT-INF/lib/")) {
|
||||
return ZipCompression.STORED;
|
||||
}
|
||||
return ZipCompression.DEFLATED;
|
||||
}
|
||||
|
||||
private LaunchScriptConfiguration enableLaunchScriptIfNecessary() {
|
||||
LaunchScriptConfiguration launchScript = this.support.getLaunchScript();
|
||||
if (launchScript == null) {
|
||||
launchScript = new LaunchScriptConfiguration();
|
||||
this.support.setLaunchScript(launchScript);
|
||||
}
|
||||
return launchScript;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.bundling.War;
|
||||
|
||||
/**
|
||||
* A custom {@link War} task that produces a Spring Boot executable war.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class BootWar extends War implements BootArchive {
|
||||
|
||||
private final BootArchiveSupport support = new BootArchiveSupport(
|
||||
"org.springframework.boot.loader.WarLauncher", this::resolveZipCompression);
|
||||
|
||||
private String mainClass;
|
||||
|
||||
private FileCollection providedClasspath;
|
||||
|
||||
/**
|
||||
* Creates a new {@code BootWar} task.
|
||||
*/
|
||||
public BootWar() {
|
||||
getWebInf().into("lib-provided",
|
||||
(copySpec) -> copySpec
|
||||
.from((Callable<Iterable<File>>) () -> this.providedClasspath == null
|
||||
? Collections.emptyList() : this.providedClasspath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy() {
|
||||
this.support.configureManifest(this, getMainClass());
|
||||
super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CopyAction createCopyAction() {
|
||||
return this.support.createCopyAction(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMainClass() {
|
||||
return this.mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainClass(String mainClass) {
|
||||
this.mainClass = mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(String... patterns) {
|
||||
this.support.requiresUnpack(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(Spec<FileTreeElement> spec) {
|
||||
this.support.requiresUnpack(spec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LaunchScriptConfiguration getLaunchScript() {
|
||||
return this.support.getLaunchScript();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchScript() {
|
||||
enableLaunchScriptIfNecessary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchScript(Action<LaunchScriptConfiguration> action) {
|
||||
action.execute(enableLaunchScriptIfNecessary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided classpath, the contents of which will be included in the
|
||||
* {@code WEB-INF/lib-provided} directory of the war.
|
||||
*
|
||||
* @return the provided classpath
|
||||
*/
|
||||
@Optional
|
||||
public FileCollection getProvidedClasspath() {
|
||||
return this.providedClasspath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds files to the provided classpath to include in the {@code WEB-INF/lib-provided}
|
||||
* directory of the war. The given {@code classpath} are evaluated as per
|
||||
* {@link Project#files(Object...)}.
|
||||
*
|
||||
* @param classpath the additions to the classpath
|
||||
*/
|
||||
public void providedClasspath(Object... classpath) {
|
||||
FileCollection existingClasspath = this.providedClasspath;
|
||||
this.providedClasspath = getProject().files(
|
||||
existingClasspath == null ? Collections.emptyList() : existingClasspath,
|
||||
classpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExcludeDevtools() {
|
||||
return this.support.isExcludeDevtools();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExcludeDevtools(boolean excludeDevtools) {
|
||||
this.support.setExcludeDevtools(excludeDevtools);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ZipCompression} that should be used when adding the file
|
||||
* represented by the given {@code details} to the jar.
|
||||
* <p>
|
||||
* By default, any file in {@code WEB-INF/lib/} or {@code WEB-INF/lib-provided/} is
|
||||
* stored and all other files are deflated.
|
||||
*
|
||||
* @param details the details
|
||||
* @return the compression to use
|
||||
*/
|
||||
protected ZipCompression resolveZipCompression(FileCopyDetails details) {
|
||||
String relativePath = details.getRelativePath().getPathString();
|
||||
if (relativePath.startsWith("WEB-INF/lib/")
|
||||
|| relativePath.startsWith("WEB-INF/lib-provided/")) {
|
||||
return ZipCompression.STORED;
|
||||
}
|
||||
return ZipCompression.DEFLATED;
|
||||
}
|
||||
|
||||
private LaunchScriptConfiguration enableLaunchScriptIfNecessary() {
|
||||
LaunchScriptConfiguration launchScript = this.support.getLaunchScript();
|
||||
if (launchScript == null) {
|
||||
launchScript = new LaunchScriptConfiguration();
|
||||
this.support.setLaunchScript(launchScript);
|
||||
}
|
||||
return launchScript;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.UnixStat;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
|
||||
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.specs.Specs;
|
||||
import org.gradle.api.tasks.WorkResult;
|
||||
import org.gradle.util.GUtil;
|
||||
|
||||
import org.springframework.boot.loader.tools.DefaultLaunchScript;
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
|
||||
/**
|
||||
* A {@link CopyAction} for creating a Spring Boot zip archive (typically a jar or war).
|
||||
* Stores jar files without compression as required by Spring Boot's loader.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class BootZipCopyAction implements CopyAction {
|
||||
|
||||
private final File output;
|
||||
|
||||
private final boolean preserveFileTimestamps;
|
||||
|
||||
private final boolean includeDefaultLoader;
|
||||
|
||||
private final Spec<FileTreeElement> requiresUnpack;
|
||||
|
||||
private final Spec<FileTreeElement> exclusions;
|
||||
|
||||
private final LaunchScriptConfiguration launchScript;
|
||||
|
||||
private final Function<FileCopyDetails, ZipCompression> compressionResolver;
|
||||
|
||||
private final String encoding;
|
||||
|
||||
BootZipCopyAction(File output, boolean preserveFileTimestamps,
|
||||
boolean includeDefaultLoader, Spec<FileTreeElement> requiresUnpack,
|
||||
Spec<FileTreeElement> exclusions, LaunchScriptConfiguration launchScript,
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver,
|
||||
String encoding) {
|
||||
this.output = output;
|
||||
this.preserveFileTimestamps = preserveFileTimestamps;
|
||||
this.includeDefaultLoader = includeDefaultLoader;
|
||||
this.requiresUnpack = requiresUnpack;
|
||||
this.exclusions = exclusions;
|
||||
this.launchScript = launchScript;
|
||||
this.compressionResolver = compressionResolver;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkResult execute(CopyActionProcessingStream stream) {
|
||||
ZipArchiveOutputStream zipStream;
|
||||
Spec<FileTreeElement> loaderEntries;
|
||||
try {
|
||||
FileOutputStream fileStream = new FileOutputStream(this.output);
|
||||
writeLaunchScriptIfNecessary(fileStream);
|
||||
zipStream = new ZipArchiveOutputStream(fileStream);
|
||||
if (this.encoding != null) {
|
||||
zipStream.setEncoding(this.encoding);
|
||||
}
|
||||
loaderEntries = writeLoaderClassesIfNecessary(zipStream);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new GradleException("Failed to create " + this.output, ex);
|
||||
}
|
||||
try {
|
||||
stream.process(new ZipStreamAction(zipStream, this.output,
|
||||
this.preserveFileTimestamps, this.requiresUnpack,
|
||||
createExclusionSpec(loaderEntries), this.compressionResolver));
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
zipStream.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
return () -> true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Spec<FileTreeElement> createExclusionSpec(
|
||||
Spec<FileTreeElement> loaderEntries) {
|
||||
return Specs.union(loaderEntries, this.exclusions);
|
||||
}
|
||||
|
||||
private Spec<FileTreeElement> writeLoaderClassesIfNecessary(
|
||||
ZipArchiveOutputStream out) {
|
||||
if (!this.includeDefaultLoader) {
|
||||
return Specs.satisfyNone();
|
||||
}
|
||||
return writeLoaderClasses(out);
|
||||
}
|
||||
|
||||
private Spec<FileTreeElement> writeLoaderClasses(ZipArchiveOutputStream out) {
|
||||
try (ZipInputStream in = new ZipInputStream(getClass()
|
||||
.getResourceAsStream("/META-INF/loader/spring-boot-loader.jar"))) {
|
||||
Set<String> entries = new HashSet<>();
|
||||
java.util.zip.ZipEntry entry;
|
||||
while ((entry = in.getNextEntry()) != null) {
|
||||
if (entry.isDirectory() && !entry.getName().startsWith("META-INF/")) {
|
||||
writeDirectory(new ZipArchiveEntry(entry), out);
|
||||
entries.add(entry.getName());
|
||||
}
|
||||
else if (entry.getName().endsWith(".class")) {
|
||||
writeClass(new ZipArchiveEntry(entry), in, out);
|
||||
}
|
||||
}
|
||||
return (element) -> {
|
||||
String path = element.getRelativePath().getPathString();
|
||||
if (element.isDirectory() && !path.endsWith(("/"))) {
|
||||
path += "/";
|
||||
}
|
||||
return entries.contains(path);
|
||||
};
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new GradleException("Failed to write loader classes", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDirectory(ZipArchiveEntry entry, ZipArchiveOutputStream out)
|
||||
throws IOException {
|
||||
if (!this.preserveFileTimestamps) {
|
||||
entry.setTime(GUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||
}
|
||||
entry.setUnixMode(UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM);
|
||||
out.putArchiveEntry(entry);
|
||||
out.closeArchiveEntry();
|
||||
}
|
||||
|
||||
private void writeClass(ZipArchiveEntry entry, ZipInputStream in,
|
||||
ZipArchiveOutputStream out) throws IOException {
|
||||
if (!this.preserveFileTimestamps) {
|
||||
entry.setTime(GUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||
}
|
||||
entry.setUnixMode(UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM);
|
||||
out.putArchiveEntry(entry);
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
out.closeArchiveEntry();
|
||||
}
|
||||
|
||||
private void writeLaunchScriptIfNecessary(FileOutputStream fileStream) {
|
||||
try {
|
||||
if (this.launchScript != null) {
|
||||
fileStream.write(new DefaultLaunchScript(this.launchScript.getScript(),
|
||||
this.launchScript.getProperties()).toByteArray());
|
||||
this.output.setExecutable(true);
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new GradleException("Failed to write launch script to " + this.output,
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ZipStreamAction
|
||||
implements CopyActionProcessingStreamAction {
|
||||
|
||||
private final ZipArchiveOutputStream zipStream;
|
||||
|
||||
private final File output;
|
||||
|
||||
private final boolean preserveFileTimestamps;
|
||||
|
||||
private final Spec<FileTreeElement> requiresUnpack;
|
||||
|
||||
private final Spec<FileTreeElement> exclusions;
|
||||
|
||||
private final Function<FileCopyDetails, ZipCompression> compressionType;
|
||||
|
||||
private ZipStreamAction(ZipArchiveOutputStream zipStream, File output,
|
||||
boolean preserveFileTimestamps, Spec<FileTreeElement> requiresUnpack,
|
||||
Spec<FileTreeElement> exclusions,
|
||||
Function<FileCopyDetails, ZipCompression> compressionType) {
|
||||
this.zipStream = zipStream;
|
||||
this.output = output;
|
||||
this.preserveFileTimestamps = preserveFileTimestamps;
|
||||
this.requiresUnpack = requiresUnpack;
|
||||
this.exclusions = exclusions;
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processFile(FileCopyDetailsInternal details) {
|
||||
if (this.exclusions.isSatisfiedBy(details)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (details.isDirectory()) {
|
||||
createDirectory(details);
|
||||
}
|
||||
else {
|
||||
createFile(details);
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new GradleException(
|
||||
"Failed to add " + details + " to " + this.output, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDirectory(FileCopyDetailsInternal details) throws IOException {
|
||||
ZipArchiveEntry archiveEntry = new ZipArchiveEntry(
|
||||
details.getRelativePath().getPathString() + '/');
|
||||
archiveEntry.setUnixMode(UnixStat.DIR_FLAG | details.getMode());
|
||||
archiveEntry.setTime(getTime(details));
|
||||
this.zipStream.putArchiveEntry(archiveEntry);
|
||||
this.zipStream.closeArchiveEntry();
|
||||
}
|
||||
|
||||
private void createFile(FileCopyDetailsInternal details) throws IOException {
|
||||
String relativePath = details.getRelativePath().getPathString();
|
||||
ZipArchiveEntry archiveEntry = new ZipArchiveEntry(relativePath);
|
||||
archiveEntry.setUnixMode(UnixStat.FILE_FLAG | details.getMode());
|
||||
archiveEntry.setTime(getTime(details));
|
||||
ZipCompression compression = this.compressionType.apply(details);
|
||||
if (compression == ZipCompression.STORED) {
|
||||
prepareStoredEntry(details, archiveEntry);
|
||||
}
|
||||
this.zipStream.putArchiveEntry(archiveEntry);
|
||||
details.copyTo(this.zipStream);
|
||||
this.zipStream.closeArchiveEntry();
|
||||
}
|
||||
|
||||
private void prepareStoredEntry(FileCopyDetailsInternal details,
|
||||
ZipArchiveEntry archiveEntry) throws IOException {
|
||||
archiveEntry.setMethod(java.util.zip.ZipEntry.STORED);
|
||||
archiveEntry.setSize(details.getSize());
|
||||
archiveEntry.setCompressedSize(details.getSize());
|
||||
Crc32OutputStream crcStream = new Crc32OutputStream();
|
||||
details.copyTo(crcStream);
|
||||
archiveEntry.setCrc(crcStream.getCrc());
|
||||
if (this.requiresUnpack.isSatisfiedBy(details)) {
|
||||
archiveEntry
|
||||
.setComment("UNPACK:" + FileUtils.sha1Hash(details.getFile()));
|
||||
}
|
||||
}
|
||||
|
||||
private long getTime(FileCopyDetails details) {
|
||||
return this.preserveFileTimestamps ? details.getLastModified()
|
||||
: GUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@code OutputStream} that provides a CRC-32 of the data that is written to it.
|
||||
*/
|
||||
private static final class Crc32OutputStream extends OutputStream {
|
||||
|
||||
private final CRC32 crc32 = new CRC32();
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
this.crc32.update(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
this.crc32.update(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
this.crc32.update(b, off, len);
|
||||
}
|
||||
|
||||
private long getCrc() {
|
||||
return this.crc32.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
|
||||
/**
|
||||
* Encapsulates the configuration of the launch script for an executable jar or war.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class LaunchScriptConfiguration implements Serializable {
|
||||
|
||||
private final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
private File script;
|
||||
|
||||
/**
|
||||
* Returns the properties that are applied to the launch script when it's being
|
||||
* including in the executable archive.
|
||||
*
|
||||
* @return the properties
|
||||
*/
|
||||
public Map<String, String> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the properties that are applied to the launch script when it's being including
|
||||
* in the executable archive.
|
||||
*
|
||||
* @param properties the properties
|
||||
*/
|
||||
public void properties(Map<String, String> properties) {
|
||||
this.properties.putAll(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script {@link File} that will be included in the executable archive.
|
||||
* When {@code null}, the default launch script will be used.
|
||||
*
|
||||
* @return the script file
|
||||
*/
|
||||
public File getScript() {
|
||||
return this.script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the script {@link File} that will be included in the executable archive. When
|
||||
* {@code null}, the default launch script will be used.
|
||||
*
|
||||
* @param script the script file
|
||||
*/
|
||||
public void setScript(File script) {
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((this.properties == null) ? 0 : this.properties.hashCode());
|
||||
result = prime * result + ((this.script == null) ? 0 : this.script.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LaunchScriptConfiguration other = (LaunchScriptConfiguration) obj;
|
||||
if (!this.properties.equals(other.properties)) {
|
||||
return false;
|
||||
}
|
||||
if (this.script == null) {
|
||||
if (other.script != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.script.equals(other.script)) {
|
||||
return false;
|
||||
}
|
||||
else if (!equalContents(this.script, other.script)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean equalContents(File one, File two) {
|
||||
try {
|
||||
return FileUtils.sha1Hash(one).equals(FileUtils.sha1Hash(two));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* An enumeration of supported compression options for an entry in a ZIP archive.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public enum ZipCompression {
|
||||
|
||||
/**
|
||||
* The entry should be {@link ZipEntry#STORED} in the archive.
|
||||
*/
|
||||
STORED,
|
||||
|
||||
/**
|
||||
* The entry should be {@link ZipEntry#DEFLATED} in the archive.
|
||||
*/
|
||||
DEFLATED
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for creating executable jars and wars.
|
||||
*/
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.run;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.SourceDirectorySet;
|
||||
import org.gradle.api.provider.PropertyState;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.InputFiles;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.SourceSetOutput;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.process.JavaExecSpec;
|
||||
|
||||
/**
|
||||
* Custom {@link JavaExec} task for running a Spring Boot application.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class BootRun extends DefaultTask {
|
||||
|
||||
private final PropertyState<String> main = getProject().property(String.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final PropertyState<List<String>> jvmArgs = (PropertyState<List<String>>) (Object) getProject()
|
||||
.property(List.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final PropertyState<List<String>> args = (PropertyState<List<String>>) (Object) getProject()
|
||||
.property(List.class);
|
||||
|
||||
private FileCollection classpath = getProject().files();
|
||||
|
||||
private List<Action<JavaExecSpec>> execSpecConfigurers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Adds the given {@code entries} to the classpath used to run the application.
|
||||
* @param entries the classpath entries
|
||||
*/
|
||||
public void classpath(Object... entries) {
|
||||
this.classpath = this.classpath.plus(getProject().files(entries));
|
||||
}
|
||||
|
||||
@InputFiles
|
||||
public FileCollection getClasspath() {
|
||||
return this.classpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@link SourceDirectorySet#getSrcDirs() source directories} of the given
|
||||
* {@code sourceSet's} {@link SourceSet#getResources() resources} to the start of the
|
||||
* classpath in place of the {@link SourceSet#getOutput output's}
|
||||
* {@link SourceSetOutput#getResourcesDir() resources directory}.
|
||||
*
|
||||
* @param sourceSet the source set
|
||||
*/
|
||||
public void sourceResources(SourceSet sourceSet) {
|
||||
this.classpath = getProject()
|
||||
.files(sourceSet.getResources().getSrcDirs(), this.classpath)
|
||||
.filter((file) -> !file.equals(sourceSet.getOutput().getResourcesDir()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main class to be run.
|
||||
* @return the main class name or {@code null}
|
||||
*/
|
||||
public String getMain() {
|
||||
return this.main.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main class to be executed using the given {@code mainProvider}.
|
||||
*
|
||||
* @param mainProvider provider of the main class name
|
||||
*/
|
||||
public void setMain(Provider<String> mainProvider) {
|
||||
this.main.set(mainProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main class to be run.
|
||||
*
|
||||
* @param main the main class name
|
||||
*/
|
||||
public void setMain(String main) {
|
||||
this.main.set(main);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JVM arguments to be used to run the application.
|
||||
* @return the JVM arguments or {@code null}
|
||||
*/
|
||||
public List<String> getJvmArgs() {
|
||||
return this.jvmArgs.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the application to be run using the JVM args provided by the given
|
||||
* {@code jvmArgsProvider}.
|
||||
*
|
||||
* @param jvmArgsProvider the provider of the JVM args
|
||||
*/
|
||||
public void setJvmArgs(Provider<List<String>> jvmArgsProvider) {
|
||||
this.jvmArgs.set(jvmArgsProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the application to be run using the given {@code jvmArgs}.
|
||||
* @param jvmArgs the JVM args
|
||||
*/
|
||||
public void setJvmArgs(List<String> jvmArgs) {
|
||||
this.jvmArgs.set(jvmArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arguments to be used to run the application.
|
||||
* @return the arguments or {@code null}
|
||||
*/
|
||||
public List<String> getArgs() {
|
||||
return this.args.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the application to be run using the given {@code args}.
|
||||
* @param args the args
|
||||
*/
|
||||
public void setArgs(List<String> args) {
|
||||
this.args.set(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the application to be run using the args provided by the given
|
||||
* {@code argsProvider}.
|
||||
* @param argsProvider the provider of the args
|
||||
*/
|
||||
public void setArgs(Provider<List<String>> argsProvider) {
|
||||
this.args.set(argsProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@code execSpecConfigurer} to be called to customize the
|
||||
* {@link JavaExecSpec} prior to running the application.
|
||||
* @param execSpecConfigurer the configurer
|
||||
*/
|
||||
public void execSpec(Action<JavaExecSpec> execSpecConfigurer) {
|
||||
this.execSpecConfigurers.add(execSpecConfigurer);
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void run() {
|
||||
getProject().javaexec((spec) -> {
|
||||
spec.classpath(this.classpath);
|
||||
spec.setMain(this.main.getOrNull());
|
||||
if (this.jvmArgs.isPresent()) {
|
||||
spec.setJvmArgs(this.jvmArgs.get());
|
||||
}
|
||||
if (this.args.isPresent()) {
|
||||
spec.setArgs(this.args.get());
|
||||
}
|
||||
if (System.console() != null) {
|
||||
// Record that the console is available here for AnsiOutput to detect
|
||||
// later
|
||||
spec.environment("spring.output.ansi.console-available", true);
|
||||
}
|
||||
this.execSpecConfigurers.forEach((configurer) -> configurer.execute(spec));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for running Spring Boot applications.
|
||||
*/
|
||||
package org.springframework.boot.gradle.tasks.run;
|
||||
@@ -0,0 +1,599 @@
|
||||
/* Javadoc style sheet */
|
||||
/*
|
||||
Overall document style
|
||||
*/
|
||||
|
||||
@import url('resources/fonts/dejavu.css');
|
||||
|
||||
body {
|
||||
background-color:#ffffff;
|
||||
color:#353833;
|
||||
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
|
||||
font-size:14px;
|
||||
margin:0;
|
||||
}
|
||||
a:link, a:visited {
|
||||
text-decoration:none;
|
||||
color:#4A6782;
|
||||
}
|
||||
a:hover, a:focus {
|
||||
text-decoration:none;
|
||||
color:#bb7a2a;
|
||||
}
|
||||
a:active {
|
||||
text-decoration:none;
|
||||
color:#4A6782;
|
||||
}
|
||||
a[name] {
|
||||
color:#353833;
|
||||
}
|
||||
a[name]:hover {
|
||||
text-decoration:none;
|
||||
color:#353833;
|
||||
}
|
||||
pre {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
}
|
||||
h1 {
|
||||
font-size:20px;
|
||||
}
|
||||
h2 {
|
||||
font-size:18px;
|
||||
}
|
||||
h3 {
|
||||
font-size:16px;
|
||||
font-style:italic;
|
||||
}
|
||||
h4 {
|
||||
font-size:13px;
|
||||
}
|
||||
h5 {
|
||||
font-size:12px;
|
||||
}
|
||||
h6 {
|
||||
font-size:11px;
|
||||
}
|
||||
ul {
|
||||
list-style-type:disc;
|
||||
}
|
||||
code, tt {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
padding-top:4px;
|
||||
margin-top:8px;
|
||||
line-height:1.4em;
|
||||
}
|
||||
dt code {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
padding-top:4px;
|
||||
}
|
||||
table tr td dt code {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
vertical-align:top;
|
||||
padding-top:4px;
|
||||
}
|
||||
sup {
|
||||
font-size:8px;
|
||||
}
|
||||
/*
|
||||
Document title and Copyright styles
|
||||
*/
|
||||
.clear {
|
||||
clear:both;
|
||||
height:0px;
|
||||
overflow:hidden;
|
||||
}
|
||||
.aboutLanguage {
|
||||
float:right;
|
||||
padding:0px 21px;
|
||||
font-size:11px;
|
||||
z-index:200;
|
||||
margin-top:-9px;
|
||||
}
|
||||
.legalCopy {
|
||||
margin-left:.5em;
|
||||
}
|
||||
.bar a, .bar a:link, .bar a:visited, .bar a:active {
|
||||
color:#FFFFFF;
|
||||
text-decoration:none;
|
||||
}
|
||||
.bar a:hover, .bar a:focus {
|
||||
color:#bb7a2a;
|
||||
}
|
||||
.tab {
|
||||
background-color:#0066FF;
|
||||
color:#ffffff;
|
||||
padding:8px;
|
||||
width:5em;
|
||||
font-weight:bold;
|
||||
}
|
||||
/*
|
||||
Navigation bar styles
|
||||
*/
|
||||
.bar {
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
padding:.8em .5em .4em .8em;
|
||||
height:auto;/*height:1.8em;*/
|
||||
font-size:11px;
|
||||
margin:0;
|
||||
}
|
||||
.topNav {
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
float:left;
|
||||
padding:0;
|
||||
width:100%;
|
||||
clear:right;
|
||||
height:2.8em;
|
||||
padding-top:10px;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.bottomNav {
|
||||
margin-top:10px;
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
float:left;
|
||||
padding:0;
|
||||
width:100%;
|
||||
clear:right;
|
||||
height:2.8em;
|
||||
padding-top:10px;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.subNav {
|
||||
background-color:#dee3e9;
|
||||
float:left;
|
||||
width:100%;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.subNav div {
|
||||
clear:left;
|
||||
float:left;
|
||||
padding:0 0 5px 6px;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
ul.navList, ul.subNavList {
|
||||
float:left;
|
||||
margin:0 25px 0 0;
|
||||
padding:0;
|
||||
}
|
||||
ul.navList li{
|
||||
list-style:none;
|
||||
float:left;
|
||||
padding: 5px 6px;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
ul.subNavList li{
|
||||
list-style:none;
|
||||
float:left;
|
||||
}
|
||||
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
|
||||
color:#FFFFFF;
|
||||
text-decoration:none;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
.topNav a:hover, .bottomNav a:hover {
|
||||
text-decoration:none;
|
||||
color:#bb7a2a;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
.navBarCell1Rev {
|
||||
background-color:#F8981D;
|
||||
color:#253441;
|
||||
margin: auto 5px;
|
||||
}
|
||||
.skipNav {
|
||||
position:absolute;
|
||||
top:auto;
|
||||
left:-9999px;
|
||||
overflow:hidden;
|
||||
}
|
||||
/*
|
||||
Page header and footer styles
|
||||
*/
|
||||
.header, .footer {
|
||||
clear:both;
|
||||
margin:0 20px;
|
||||
padding:5px 0 0 0;
|
||||
}
|
||||
.indexHeader {
|
||||
margin:10px;
|
||||
position:relative;
|
||||
}
|
||||
.indexHeader span{
|
||||
margin-right:15px;
|
||||
}
|
||||
.indexHeader h1 {
|
||||
font-size:13px;
|
||||
}
|
||||
.title {
|
||||
color:#2c4557;
|
||||
margin:10px 0;
|
||||
}
|
||||
.subTitle {
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
.header ul {
|
||||
margin:0 0 15px 0;
|
||||
padding:0;
|
||||
}
|
||||
.footer ul {
|
||||
margin:20px 0 5px 0;
|
||||
}
|
||||
.header ul li, .footer ul li {
|
||||
list-style:none;
|
||||
font-size:13px;
|
||||
}
|
||||
/*
|
||||
Heading styles
|
||||
*/
|
||||
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
|
||||
background-color:#dee3e9;
|
||||
border:1px solid #d0d9e0;
|
||||
margin:0 0 6px -8px;
|
||||
padding:7px 5px;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList li.blockList h3 {
|
||||
background-color:#dee3e9;
|
||||
border:1px solid #d0d9e0;
|
||||
margin:0 0 6px -8px;
|
||||
padding:7px 5px;
|
||||
}
|
||||
ul.blockList ul.blockList li.blockList h3 {
|
||||
padding:0;
|
||||
margin:15px 0;
|
||||
}
|
||||
ul.blockList li.blockList h2 {
|
||||
padding:0px 0 20px 0;
|
||||
}
|
||||
/*
|
||||
Page layout container styles
|
||||
*/
|
||||
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
|
||||
clear:both;
|
||||
padding:10px 20px;
|
||||
position:relative;
|
||||
}
|
||||
.indexContainer {
|
||||
margin:10px;
|
||||
position:relative;
|
||||
font-size:12px;
|
||||
}
|
||||
.indexContainer h2 {
|
||||
font-size:13px;
|
||||
padding:0 0 3px 0;
|
||||
}
|
||||
.indexContainer ul {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.indexContainer ul li {
|
||||
list-style:none;
|
||||
padding-top:2px;
|
||||
}
|
||||
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
|
||||
font-size:12px;
|
||||
font-weight:bold;
|
||||
margin:10px 0 0 0;
|
||||
color:#4E4E4E;
|
||||
}
|
||||
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
|
||||
margin:5px 0 10px 0px;
|
||||
font-size:14px;
|
||||
font-family:'DejaVu Sans Mono',monospace;
|
||||
}
|
||||
.serializedFormContainer dl.nameValue dt {
|
||||
margin-left:1px;
|
||||
font-size:1.1em;
|
||||
display:inline;
|
||||
font-weight:bold;
|
||||
}
|
||||
.serializedFormContainer dl.nameValue dd {
|
||||
margin:0 0 0 1px;
|
||||
font-size:1.1em;
|
||||
display:inline;
|
||||
}
|
||||
/*
|
||||
List styles
|
||||
*/
|
||||
ul.horizontal li {
|
||||
display:inline;
|
||||
font-size:0.9em;
|
||||
}
|
||||
ul.inheritance {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
ul.inheritance li {
|
||||
display:inline;
|
||||
list-style:none;
|
||||
}
|
||||
ul.inheritance li ul.inheritance {
|
||||
margin-left:15px;
|
||||
padding-left:15px;
|
||||
padding-top:1px;
|
||||
}
|
||||
ul.blockList, ul.blockListLast {
|
||||
margin:10px 0 10px 0;
|
||||
padding:0;
|
||||
}
|
||||
ul.blockList li.blockList, ul.blockListLast li.blockList {
|
||||
list-style:none;
|
||||
margin-bottom:15px;
|
||||
line-height:1.4;
|
||||
}
|
||||
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
|
||||
padding:0px 20px 5px 10px;
|
||||
border:1px solid #ededed;
|
||||
background-color:#f8f8f8;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
|
||||
padding:0 0 5px 8px;
|
||||
background-color:#ffffff;
|
||||
border:none;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
|
||||
margin-left:0;
|
||||
padding-left:0;
|
||||
padding-bottom:15px;
|
||||
border:none;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
|
||||
list-style:none;
|
||||
border-bottom:none;
|
||||
padding-bottom:0;
|
||||
}
|
||||
table tr td dl, table tr td dl dt, table tr td dl dd {
|
||||
margin-top:0;
|
||||
margin-bottom:1px;
|
||||
}
|
||||
/*
|
||||
Table styles
|
||||
*/
|
||||
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
|
||||
width:100%;
|
||||
border-left:1px solid #EEE;
|
||||
border-right:1px solid #EEE;
|
||||
border-bottom:1px solid #EEE;
|
||||
}
|
||||
.overviewSummary, .memberSummary {
|
||||
padding:0px;
|
||||
}
|
||||
.overviewSummary caption, .memberSummary caption, .typeSummary caption,
|
||||
.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
|
||||
position:relative;
|
||||
text-align:left;
|
||||
background-repeat:no-repeat;
|
||||
color:#253441;
|
||||
font-weight:bold;
|
||||
clear:none;
|
||||
overflow:hidden;
|
||||
padding:0px;
|
||||
padding-top:10px;
|
||||
padding-left:1px;
|
||||
margin:0px;
|
||||
white-space:pre;
|
||||
}
|
||||
.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
|
||||
.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
|
||||
.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
|
||||
.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
|
||||
.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
|
||||
.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
|
||||
.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
|
||||
.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
|
||||
color:#FFFFFF;
|
||||
}
|
||||
.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
|
||||
.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
padding-bottom:7px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
border: none;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.activeTableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
margin-right:3px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.tableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
margin-right:3px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#4D7A97;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
|
||||
padding-top:0px;
|
||||
padding-left:0px;
|
||||
padding-right:0px;
|
||||
background-image:none;
|
||||
float:none;
|
||||
display:inline;
|
||||
}
|
||||
.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
|
||||
.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
position:relative;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
}
|
||||
.memberSummary .activeTableTab .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
margin-right:3px;
|
||||
position:relative;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
}
|
||||
.memberSummary .tableTab .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
margin-right:3px;
|
||||
position:relative;
|
||||
background-color:#4D7A97;
|
||||
float:left;
|
||||
|
||||
}
|
||||
.overviewSummary td, .memberSummary td, .typeSummary td,
|
||||
.useSummary td, .constantsSummary td, .deprecatedSummary td {
|
||||
text-align:left;
|
||||
padding:0px 0px 12px 10px;
|
||||
width:100%;
|
||||
}
|
||||
th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
|
||||
td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
|
||||
vertical-align:top;
|
||||
padding-right:0px;
|
||||
padding-top:8px;
|
||||
padding-bottom:3px;
|
||||
}
|
||||
th.colFirst, th.colLast, th.colOne, .constantsSummary th {
|
||||
background:#dee3e9;
|
||||
text-align:left;
|
||||
padding:8px 3px 3px 7px;
|
||||
}
|
||||
td.colFirst, th.colFirst {
|
||||
white-space:nowrap;
|
||||
font-size:13px;
|
||||
}
|
||||
td.colLast, th.colLast {
|
||||
font-size:13px;
|
||||
}
|
||||
td.colOne, th.colOne {
|
||||
font-size:13px;
|
||||
}
|
||||
.overviewSummary td.colFirst, .overviewSummary th.colFirst,
|
||||
.overviewSummary td.colOne, .overviewSummary th.colOne,
|
||||
.memberSummary td.colFirst, .memberSummary th.colFirst,
|
||||
.memberSummary td.colOne, .memberSummary th.colOne,
|
||||
.typeSummary td.colFirst{
|
||||
width:25%;
|
||||
vertical-align:top;
|
||||
}
|
||||
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
|
||||
font-weight:bold;
|
||||
}
|
||||
.tableSubHeadingColor {
|
||||
background-color:#EEEEFF;
|
||||
}
|
||||
.altColor {
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
.rowColor {
|
||||
background-color:#EEEEEF;
|
||||
}
|
||||
/*
|
||||
Content styles
|
||||
*/
|
||||
.description pre {
|
||||
margin-top:0;
|
||||
}
|
||||
.deprecatedContent {
|
||||
margin:0;
|
||||
padding:10px 0;
|
||||
}
|
||||
.docSummary {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
ul.blockList ul.blockList ul.blockList li.blockList h3 {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.block {
|
||||
font-size:14px;
|
||||
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
|
||||
}
|
||||
|
||||
td.colLast div {
|
||||
padding-top:0px;
|
||||
}
|
||||
|
||||
|
||||
td.colLast a {
|
||||
padding-bottom:3px;
|
||||
}
|
||||
/*
|
||||
Formatting effect styles
|
||||
*/
|
||||
.sourceLineNo {
|
||||
color:green;
|
||||
padding:0 30px 0 0;
|
||||
}
|
||||
h1.hidden {
|
||||
visibility:hidden;
|
||||
overflow:hidden;
|
||||
font-size:10px;
|
||||
}
|
||||
.block {
|
||||
display:block;
|
||||
margin:3px 10px 2px 0px;
|
||||
color:#474747;
|
||||
}
|
||||
.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
|
||||
.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
|
||||
.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
|
||||
font-weight:bold;
|
||||
}
|
||||
.deprecationComment, .emphasizedPhrase, .interfaceName {
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
|
||||
div.block div.block span.interfaceName {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.contentContainer ul.blockList li.blockList h2{
|
||||
padding-bottom:0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Spring
|
||||
*/
|
||||
|
||||
pre.code {
|
||||
background-color: #F8F8F8;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-radius: 3px 3px 3px 3px;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
margin: 4px 20px 2px 0px;
|
||||
}
|
||||
|
||||
pre.code code, pre.code code * {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre.code code, pre.code code * {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=org.springframework.boot.gradle.plugin.SpringBootPlugin
|
||||
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## ${applicationName} start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: \$0 may be a link
|
||||
PRG="\$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "\$PRG" ] ; do
|
||||
ls=`ls -ld "\$PRG"`
|
||||
link=`expr "\$ls" : '.*-> \\(.*\\)\$'`
|
||||
if expr "\$link" : '/.*' > /dev/null; then
|
||||
PRG="\$link"
|
||||
else
|
||||
PRG=`dirname "\$PRG"`"/\$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"\$PRG\"`/${appHomeRelativePath}" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "\$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="${applicationName}"
|
||||
APP_BASE_NAME=`basename "\$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and ${optsEnvironmentVar} to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=${defaultJvmOpts}
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "\$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "\$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
JARPATH=$classpath
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "\$JAVA_HOME" ] ; then
|
||||
if [ -x "\$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="\$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="\$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "\$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: \$JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "\$cygwin" = "false" -a "\$darwin" = "false" -a "\$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ \$? -eq 0 ] ; then
|
||||
if [ "\$MAX_FD" = "maximum" -o "\$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="\$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n \$MAX_FD
|
||||
if [ \$? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: \$MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: \$MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if \$darwin; then
|
||||
GRADLE_OPTS="\$GRADLE_OPTS \\"-Xdock:name=\$APP_NAME\\" \\"-Xdock:icon=\$APP_HOME/media/gradle.icns\\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if \$cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "\$APP_HOME"`
|
||||
JARPATH=`cygpath --path --mixed "\$JARPATH"`
|
||||
JAVACMD=`cygpath --unix "\$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in \$ROOTDIRSRAW ; do
|
||||
ROOTDIRS="\$ROOTDIRS\$SEP\$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^(\$ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "\$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="\$OURCYGPATTERN|(\$GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "\$@" ; do
|
||||
CHECK=`echo "\$arg"|egrep -c "\$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "\$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ \$CHECK -ne 0 ] && [ \$CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args\$i`=`cygpath --path --ignore --mixed "\$arg"`
|
||||
else
|
||||
eval `echo args\$i`="\"\$arg\""
|
||||
fi
|
||||
i=\$((i+1))
|
||||
done
|
||||
case \$i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "\$args0" ;;
|
||||
(2) set -- "\$args0" "\$args1" ;;
|
||||
(3) set -- "\$args0" "\$args1" "\$args2" ;;
|
||||
(4) set -- "\$args0" "\$args1" "\$args2" "\$args3" ;;
|
||||
(5) set -- "\$args0" "\$args1" "\$args2" "\$args3" "\$args4" ;;
|
||||
(6) set -- "\$args0" "\$args1" "\$args2" "\$args3" "\$args4" "\$args5" ;;
|
||||
(7) set -- "\$args0" "\$args1" "\$args2" "\$args3" "\$args4" "\$args5" "\$args6" ;;
|
||||
(8) set -- "\$args0" "\$args1" "\$args2" "\$args3" "\$args4" "\$args5" "\$args6" "\$args7" ;;
|
||||
(9) set -- "\$args0" "\$args1" "\$args2" "\$args3" "\$args4" "\$args5" "\$args6" "\$args7" "\$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save ( ) {
|
||||
for i do printf %s\\\\n "\$i" | sed "s/'/'\\\\\\\\''/g;1s/^/'/;\\\$s/\\\$/' \\\\\\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=\$(save "\$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- \$DEFAULT_JVM_OPTS \$JAVA_OPTS \$${optsEnvironmentVar} <% if ( appNameSystemProperty ) { %>"\"-D${appNameSystemProperty}=\$APP_BASE_NAME\"" <% } %>-jar "\"\$JARPATH\"" "\$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "\$(uname)" = "Darwin" ] && [ "\$HOME" = "\$PWD" ]; then
|
||||
cd "\$(dirname "\$0")"
|
||||
fi
|
||||
|
||||
exec "\$JAVACMD" "\$@"
|
||||
@@ -0,0 +1,85 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem ${applicationName} startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.\
|
||||
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%${appHomeRelativePath}
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and ${optsEnvironmentVar} to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=${defaultJvmOpts}
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set JARPATH=$classpath
|
||||
|
||||
@rem Execute ${applicationName}
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %${optsEnvironmentVar}% <% if ( appNameSystemProperty ) { %>"-D${appNameSystemProperty}=%APP_BASE_NAME%"<% } %> -jar "%JARPATH%" %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable ${exitEnvironmentVar} if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%${exitEnvironmentVar}%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Very basic application used for testing {@code BootRun}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BootRunApplication {
|
||||
|
||||
protected BootRunApplication() {
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
dumpClassPath();
|
||||
dumpArgs(args);
|
||||
dumpJvmArgs();
|
||||
}
|
||||
|
||||
private static void dumpClassPath() {
|
||||
int i = 1;
|
||||
for (String entry : ManagementFactory.getRuntimeMXBean().getClassPath()
|
||||
.split(File.pathSeparator)) {
|
||||
System.out.println(i++ + ". " + entry);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpArgs(String[] args) {
|
||||
System.out.println(Arrays.toString(args));
|
||||
}
|
||||
|
||||
private static void dumpJvmArgs() {
|
||||
System.out.println(ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
/**
|
||||
* Tests for the getting started documentation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class GettingStartedDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void applyPluginSnapshotExampleEvaluatesSuccessfully() {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/getting-started/apply-plugin-snapshot.gradle")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typicalPluginsAppliesExceptedPlugins() {
|
||||
this.gradleBuild.script("src/main/gradle/getting-started/typical-plugins.gradle")
|
||||
.build("verify");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for the generating build info documentation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class IntegratingWithActuatorDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void basicBuildInfo() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/integrating-with-actuator/build-info-basic.gradle")
|
||||
.build("bootBuildInfo");
|
||||
assertThat(new File(this.gradleBuild.getProjectDir(),
|
||||
"build/resources/main/META-INF/build-info.properties")).isFile();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildInfoCustomValues() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/integrating-with-actuator/build-info-custom-values.gradle")
|
||||
.build("bootBuildInfo");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/resources/main/META-INF/build-info.properties");
|
||||
assertThat(file).isFile();
|
||||
Properties properties = buildInfoProperties(file);
|
||||
assertThat(properties).containsEntry("build.artifact", "example-app");
|
||||
assertThat(properties).containsEntry("build.version", "1.2.3");
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.name", "Example application");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildInfoAdditional() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/integrating-with-actuator/build-info-additional.gradle")
|
||||
.build("bootBuildInfo");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/resources/main/META-INF/build-info.properties");
|
||||
assertThat(file).isFile();
|
||||
Properties properties = buildInfoProperties(file);
|
||||
assertThat(properties).containsEntry("build.a", "alpha");
|
||||
assertThat(properties).containsEntry("build.b", "bravo");
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties(File file) {
|
||||
assertThat(file).isFile();
|
||||
Properties properties = new Properties();
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
properties.load(reader);
|
||||
return properties;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for the managing dependencies documentation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ManagingDependenciesDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void dependenciesExampleEvaluatesSuccessfully() {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/managing-dependencies/dependencies.gradle")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customManagedVersions() {
|
||||
assertThat(this.gradleBuild
|
||||
.script("src/main/gradle/managing-dependencies/custom-version.gradle")
|
||||
.build("slf4jVersion").getOutput()).contains("1.7.20");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for the packaging documentation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PackagingDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void warContainerDependencyEvaluatesSuccessfully() {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/war-container-dependency.gradle")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarMainClass() throws IOException {
|
||||
this.gradleBuild.script("src/main/gradle/packaging/boot-jar-main-class.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
assertThat(jar.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.ExampleApplication");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarManifestMainClass() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-jar-manifest-main-class.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
assertThat(jar.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.ExampleApplication");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginMainClass() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/application-plugin-main-class.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
assertThat(jar.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.ExampleApplication");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootWarIncludeDevtools() throws IOException {
|
||||
new File(this.gradleBuild.getProjectDir(),
|
||||
"spring-boot-devtools-1.2.3.RELEASE.jar").createNewFile();
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-war-include-devtools.gradle")
|
||||
.build("bootWar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
assertThat(jar.getEntry("WEB-INF/lib/spring-boot-devtools-1.2.3.RELEASE.jar"))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarRequiresUnpack() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-jar-requires-unpack.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
JarEntry entry = jar.getJarEntry("BOOT-INF/lib/jruby-complete-1.7.25.jar");
|
||||
assertThat(entry).isNotNull();
|
||||
assertThat(entry.getComment()).startsWith("UNPACK:");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarIncludeLaunchScript() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-jar-include-launch-script.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
assertThat(FileCopyUtils.copyToString(new FileReader(file)))
|
||||
.startsWith("#!/bin/bash");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarLaunchScriptProperties() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-jar-launch-script-properties.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
assertThat(FileCopyUtils.copyToString(new FileReader(file)))
|
||||
.contains("example-app.log");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarCustomLaunchScript() throws IOException {
|
||||
File customScriptFile = new File(this.gradleBuild.getProjectDir(),
|
||||
"src/custom.script");
|
||||
customScriptFile.getParentFile().mkdirs();
|
||||
FileCopyUtils.copy("custom", new FileWriter(customScriptFile));
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-jar-custom-launch-script.gradle")
|
||||
.build("bootJar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(file).isFile();
|
||||
assertThat(FileCopyUtils.copyToString(new FileReader(file))).startsWith("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootWarPropertiesLauncher() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/packaging/boot-war-properties-launcher.gradle")
|
||||
.build("bootWar");
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war");
|
||||
assertThat(file).isFile();
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
assertThat(jar.getManifest().getMainAttributes().getValue("Main-Class"))
|
||||
.isEqualTo("org.springframework.boot.loader.PropertiesLauncher");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootJarAndJar() throws IOException {
|
||||
this.gradleBuild.script("src/main/gradle/packaging/boot-jar-and-jar.gradle")
|
||||
.build("assemble");
|
||||
File jar = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
|
||||
assertThat(jar).isFile();
|
||||
File bootJar = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-boot.jar");
|
||||
assertThat(bootJar).isFile();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for the publishing documentation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PublishingDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void mavenUpload() throws IOException {
|
||||
assertThat(this.gradleBuild.script("src/main/gradle/publishing/maven.gradle")
|
||||
.build("deployerRepository").getOutput())
|
||||
.contains("https://repo.example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mavenPublish() throws IOException {
|
||||
assertThat(
|
||||
this.gradleBuild.script("src/main/gradle/publishing/maven-publish.gradle")
|
||||
.build("publishingConfiguration").getOutput())
|
||||
.contains("MavenPublication")
|
||||
.contains("https://repo.example.com");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.docs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for the documentation about running a Spring Boot application.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RunningDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void bootRunMain() throws IOException {
|
||||
assertThat(this.gradleBuild.script("src/main/gradle/running/boot-run-main.gradle")
|
||||
.build("configuredMainClass").getOutput())
|
||||
.contains("com.example.ExampleApplication");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginMainClassName() throws IOException {
|
||||
assertThat(this.gradleBuild
|
||||
.script("src/main/gradle/running/application-plugin-main-class-name.gradle")
|
||||
.build("configuredMainClass").getOutput())
|
||||
.contains("com.example.ExampleApplication");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootRunSourceResources() throws IOException {
|
||||
assertThat(this.gradleBuild
|
||||
.script("src/main/gradle/running/boot-run-source-resources.gradle")
|
||||
.build("configuredClasspath").getOutput())
|
||||
.contains(new File("src/main/resources").getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootRunExecSpecCustomization() throws IOException {
|
||||
this.gradleBuild
|
||||
.script("src/main/gradle/running/boot-run-custom-exec-spec.gradle")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BuildInfo} created using the
|
||||
* {@link org.springframework.boot.gradle.dsl.SpringBootExtension DSL}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BuildInfoDslIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public final GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void basicJar() throws IOException {
|
||||
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties properties = buildInfoProperties();
|
||||
assertThat(properties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.artifact",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.version", "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jarWithCustomName() throws IOException {
|
||||
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties properties = buildInfoProperties();
|
||||
assertThat(properties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.artifact", "foo");
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.version", "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicWar() throws IOException {
|
||||
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties properties = buildInfoProperties();
|
||||
assertThat(properties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.artifact",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.version", "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void warWithCustomName() throws IOException {
|
||||
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties properties = buildInfoProperties();
|
||||
assertThat(properties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.artifact", "foo");
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.version", "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalProperties() throws IOException {
|
||||
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties properties = buildInfoProperties();
|
||||
assertThat(properties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.artifact",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(properties).containsEntry("build.group", "com.example");
|
||||
assertThat(properties).containsEntry("build.version", "1.0");
|
||||
assertThat(properties).containsEntry("build.a", "alpha");
|
||||
assertThat(properties).containsEntry("build.b", "bravo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classesDependency() throws IOException {
|
||||
assertThat(this.gradleBuild.build("classes", "--stacktrace")
|
||||
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties() {
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/resources/main/META-INF/build-info.properties");
|
||||
assertThat(file).isFile();
|
||||
Properties properties = new Properties();
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
properties.load(reader);
|
||||
return properties;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.junit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Rule;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
/**
|
||||
* Custom {@link Suite} that runs tests against multiple version of Gradle. Test classes
|
||||
* using the suite must have a public {@link GradleBuild} field named {@code gradleBuild}
|
||||
* and annotated with {@link Rule}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public final class GradleCompatibilitySuite extends Suite {
|
||||
|
||||
private static final List<String> GRADLE_VERSIONS = Arrays.asList("default", "4.1",
|
||||
"4.2");
|
||||
|
||||
public GradleCompatibilitySuite(Class<?> clazz) throws InitializationError {
|
||||
super(clazz, createRunners(clazz));
|
||||
}
|
||||
|
||||
private static List<Runner> createRunners(Class<?> clazz) throws InitializationError {
|
||||
List<Runner> runners = new ArrayList<>();
|
||||
for (String version : GRADLE_VERSIONS) {
|
||||
runners.add(new GradleCompatibilityClassRunner(clazz, version));
|
||||
}
|
||||
return runners;
|
||||
}
|
||||
|
||||
private static final class GradleCompatibilityClassRunner
|
||||
extends BlockJUnit4ClassRunner {
|
||||
|
||||
private final String gradleVersion;
|
||||
|
||||
private GradleCompatibilityClassRunner(Class<?> klass, String gradleVersion)
|
||||
throws InitializationError {
|
||||
super(klass);
|
||||
this.gradleVersion = gradleVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createTest() throws Exception {
|
||||
Object test = super.createTest();
|
||||
configureTest(test);
|
||||
return test;
|
||||
}
|
||||
|
||||
private void configureTest(Object test) throws Exception {
|
||||
GradleBuild gradleBuild = new GradleBuild();
|
||||
if (!"default".equals(this.gradleVersion)) {
|
||||
gradleBuild = gradleBuild.gradleVersion(this.gradleVersion);
|
||||
}
|
||||
test.getClass().getField("gradleBuild").set(test, gradleBuild);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName() {
|
||||
return "Gradle " + this.gradleVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String testName(FrameworkMethod method) {
|
||||
return method.getName() + " [" + getName() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ApplicationPluginAction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class ApplicationPluginActionIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void noBootDistributionWithoutApplicationPluginApplied() {
|
||||
assertThat(this.gradleBuild.build("distributionExists", "-PdistributionName=boot")
|
||||
.getOutput()).contains("boot exists = false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyingApplicationPluginCreatesBootDistribution() {
|
||||
assertThat(this.gradleBuild.build("distributionExists", "-PdistributionName=boot",
|
||||
"-PapplyApplicationPlugin").getOutput()).contains("boot exists = true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noBootStartScriptsTaskWithoutApplicationPluginApplied() {
|
||||
assertThat(this.gradleBuild.build("taskExists", "-PtaskName=bootStartScripts")
|
||||
.getOutput()).contains("bootStartScripts exists = false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyingApplicationPluginCreatesBootStartScriptsTask() {
|
||||
assertThat(this.gradleBuild.build("taskExists", "-PtaskName=bootStartScripts",
|
||||
"-PapplyApplicationPlugin").getOutput())
|
||||
.contains("bootStartScripts exists = true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipDistributionForJarCanBeBuilt() throws IOException {
|
||||
assertThat(
|
||||
this.gradleBuild.build("bootDistZip").task(":bootDistZip").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
File distribution = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/distributions/" + name + "-boot.zip");
|
||||
assertThat(distribution).isFile();
|
||||
assertThat(zipEntryNames(distribution)).containsExactlyInAnyOrder(name + "-boot/",
|
||||
name + "-boot/lib/", name + "-boot/lib/" + name + ".jar",
|
||||
name + "-boot/bin/", name + "-boot/bin/" + name,
|
||||
name + "-boot/bin/" + name + ".bat");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tarDistributionForJarCanBeBuilt() throws IOException {
|
||||
assertThat(
|
||||
this.gradleBuild.build("bootDistTar").task(":bootDistTar").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
File distribution = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/distributions/" + name + "-boot.tar");
|
||||
assertThat(distribution).isFile();
|
||||
assertThat(tarEntryNames(distribution)).containsExactlyInAnyOrder(name + "-boot/",
|
||||
name + "-boot/lib/", name + "-boot/lib/" + name + ".jar",
|
||||
name + "-boot/bin/", name + "-boot/bin/" + name,
|
||||
name + "-boot/bin/" + name + ".bat");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipDistributionForWarCanBeBuilt() throws IOException {
|
||||
assertThat(
|
||||
this.gradleBuild.build("bootDistZip").task(":bootDistZip").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
File distribution = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/distributions/" + name + "-boot.zip");
|
||||
assertThat(distribution).isFile();
|
||||
assertThat(zipEntryNames(distribution)).containsExactlyInAnyOrder(name + "-boot/",
|
||||
name + "-boot/lib/", name + "-boot/lib/" + name + ".war",
|
||||
name + "-boot/bin/", name + "-boot/bin/" + name,
|
||||
name + "-boot/bin/" + name + ".bat");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tarDistributionForWarCanBeBuilt() throws IOException {
|
||||
assertThat(
|
||||
this.gradleBuild.build("bootDistTar").task(":bootDistTar").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
File distribution = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/distributions/" + name + "-boot.tar");
|
||||
assertThat(distribution).isFile();
|
||||
assertThat(tarEntryNames(distribution)).containsExactlyInAnyOrder(name + "-boot/",
|
||||
name + "-boot/lib/", name + "-boot/lib/" + name + ".war",
|
||||
name + "-boot/bin/", name + "-boot/bin/" + name,
|
||||
name + "-boot/bin/" + name + ".bat");
|
||||
}
|
||||
|
||||
private List<String> zipEntryNames(File distribution) throws IOException {
|
||||
List<String> entryNames = new ArrayList<>();
|
||||
try (ZipFile zipFile = new ZipFile(distribution)) {
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
entryNames.add(entries.nextElement().getName());
|
||||
}
|
||||
}
|
||||
return entryNames;
|
||||
}
|
||||
|
||||
private List<String> tarEntryNames(File distribution) throws IOException {
|
||||
List<String> entryNames = new ArrayList<>();
|
||||
try (TarArchiveInputStream input = new TarArchiveInputStream(
|
||||
new FileInputStream(distribution))) {
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = input.getNextTarEntry()) != null) {
|
||||
entryNames.add(entry.getName());
|
||||
}
|
||||
}
|
||||
return entryNames;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for the configuration applied by
|
||||
* {@link DependencyManagementPluginAction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class DependencyManagementPluginActionIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void noDependencyManagementIsAppliedByDefault() {
|
||||
assertThat(this.gradleBuild.build("doesNotHaveDependencyManagement")
|
||||
.task(":doesNotHaveDependencyManagement").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bomIsImportedWhenDependencyManagementPluginIsApplied() {
|
||||
assertThat(this.gradleBuild
|
||||
.build("hasDependencyManagement", "-PapplyDependencyManagementPlugin")
|
||||
.task(":hasDependencyManagement").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void helpfulErrorWhenVersionlessDependencyFailsToResolve() throws IOException {
|
||||
File examplePackage = new File(this.gradleBuild.getProjectDir(),
|
||||
"src/main/java/com/example");
|
||||
examplePackage.mkdirs();
|
||||
FileSystemUtils.copyRecursively(new File("src/test/java/com/example"),
|
||||
examplePackage);
|
||||
BuildResult result = this.gradleBuild.buildAndFail("compileJava");
|
||||
assertThat(result.task(":compileJava").getOutcome())
|
||||
.isEqualTo(TaskOutcome.FAILED);
|
||||
String output = result.getOutput();
|
||||
assertThat(output).contains("During the build, one or more dependencies that "
|
||||
+ "were declared without a version failed to resolve:");
|
||||
assertThat(output).contains("org.springframework.boot:spring-boot-starter-web:");
|
||||
assertThat(output).contains("Did you forget to apply the "
|
||||
+ "io.spring.dependency-management plugin to the "
|
||||
+ this.gradleBuild.getProjectDir().getName() + " project?");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link WarPluginAction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class JavaPluginActionIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void noBootJarTaskWithoutJavaPluginApplied() {
|
||||
assertThat(this.gradleBuild.build("taskExists", "-PtaskName=bootJar").getOutput())
|
||||
.contains("bootJar exists = false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyingJavaPluginCreatesBootJarTask() {
|
||||
assertThat(this.gradleBuild
|
||||
.build("taskExists", "-PtaskName=bootJar", "-PapplyJavaPlugin")
|
||||
.getOutput()).contains("bootJar exists = true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noBootRunTaskWithoutJavaPluginApplied() {
|
||||
assertThat(this.gradleBuild.build("taskExists", "-PtaskName=bootRun").getOutput())
|
||||
.contains("bootRun exists = false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyingJavaPluginCreatesBootRunTask() {
|
||||
assertThat(this.gradleBuild
|
||||
.build("taskExists", "-PtaskName=bootRun", "-PapplyJavaPlugin")
|
||||
.getOutput()).contains("bootRun exists = true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void javaCompileTasksUseUtf8Encoding() {
|
||||
assertThat(this.gradleBuild.build("javaCompileEncoding", "-PapplyJavaPlugin")
|
||||
.getOutput()).contains("compileJava = UTF-8")
|
||||
.contains("compileTestJava = UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void javaCompileTasksUseParametersCompilerFlagByDefault() {
|
||||
assertThat(this.gradleBuild.build("javaCompileTasksCompilerArgs").getOutput())
|
||||
.contains("compileJava compiler args: [-parameters]")
|
||||
.contains("compileTestJava compiler args: [-parameters]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void javaCompileTasksUseParametersAndAdditionalCompilerFlags() {
|
||||
assertThat(this.gradleBuild.build("javaCompileTasksCompilerArgs").getOutput())
|
||||
.contains("compileJava compiler args: [-parameters, -Xlint:all]")
|
||||
.contains("compileTestJava compiler args: [-parameters, -Xlint:all]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void javaCompileTasksCanOverrideDefaultParametersCompilerFlag() {
|
||||
assertThat(this.gradleBuild.build("javaCompileTasksCompilerArgs").getOutput())
|
||||
.contains("compileJava compiler args: [-Xlint:all]")
|
||||
.contains("compileTestJava compiler args: [-Xlint:all]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assembleRunsBootJarAndJarIsSkipped() {
|
||||
BuildResult result = this.gradleBuild.build("assemble");
|
||||
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jarAndBootJarCanBothBeBuilt() {
|
||||
BuildResult result = this.gradleBuild.build("assemble");
|
||||
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
|
||||
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
|
||||
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"),
|
||||
new File(buildLibs,
|
||||
this.gradleBuild.getProjectDir().getName() + "-boot.jar"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MavenPluginAction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class MavenPluginActionIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void clearsConf2ScopeMappingsOfUploadBootArchivesTask() {
|
||||
assertThat(this.gradleBuild.build("conf2ScopeMappings").getOutput())
|
||||
.contains("Conf2ScopeMappings = 0");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link SpringBootPlugin}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class SpringBootPluginIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public final GradleBuild gradleBuild = new GradleBuild();
|
||||
|
||||
@Test
|
||||
public void failFastWithVersionOfGradleLowerThanRequired() {
|
||||
BuildResult result = this.gradleBuild.gradleVersion("3.5.1").buildAndFail();
|
||||
assertThat(result.getOutput()).contains("Spring Boot plugin requires Gradle 4.0"
|
||||
+ " or later. The current version is Gradle 3.5.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void succeedWithVersionOfGradleHigherThanRequired() {
|
||||
this.gradleBuild.gradleVersion("4.0.1").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void succeedWithVersionOfGradleMatchingWhatIsRequired() {
|
||||
this.gradleBuild.gradleVersion("4.0").build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JavaPluginAction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class WarPluginActionIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void noBootWarTaskWithoutWarPluginApplied() {
|
||||
assertThat(this.gradleBuild.build("taskExists", "-PtaskName=bootWar").getOutput())
|
||||
.contains("bootWar exists = false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyingWarPluginCreatesBootWarTask() {
|
||||
assertThat(this.gradleBuild
|
||||
.build("taskExists", "-PtaskName=bootWar", "-PapplyWarPlugin")
|
||||
.getOutput()).contains("bootWar exists = true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assembleRunsBootWarAndWarIsSkipped() {
|
||||
BuildResult result = this.gradleBuild.build("assemble");
|
||||
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void warAndBootWarCanBothBeBuilt() {
|
||||
BuildResult result = this.gradleBuild.build("assemble");
|
||||
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
|
||||
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
|
||||
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"),
|
||||
new File(buildLibs,
|
||||
this.gradleBuild.getProjectDir().getName() + "-boot.war"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link BuildInfo} task.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class BuildInfoIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void defaultValues() {
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties buildInfoProperties = buildInfoProperties();
|
||||
assertThat(buildInfoProperties).containsKey("build.time");
|
||||
assertThat(buildInfoProperties).containsEntry("build.artifact", "unspecified");
|
||||
assertThat(buildInfoProperties).containsEntry("build.group", "");
|
||||
assertThat(buildInfoProperties).containsEntry("build.name",
|
||||
this.gradleBuild.getProjectDir().getName());
|
||||
assertThat(buildInfoProperties).containsEntry("build.version", "unspecified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicExecution() {
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties buildInfoProperties = buildInfoProperties();
|
||||
assertThat(buildInfoProperties).containsKey("build.time");
|
||||
assertThat(buildInfoProperties).containsEntry("build.artifact", "foo");
|
||||
assertThat(buildInfoProperties).containsEntry("build.group", "foo");
|
||||
assertThat(buildInfoProperties).containsEntry("build.additional", "foo");
|
||||
assertThat(buildInfoProperties).containsEntry("build.name", "foo");
|
||||
assertThat(buildInfoProperties).containsEntry("build.version", "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upToDateWhenExecutedTwice() {
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenDestinationDirChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoDestinationDir");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectArtifactChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoArtifact");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectGroupChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoGroup");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectVersionChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoVersion");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectNameChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenAdditionalPropertyChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoAdditional");
|
||||
}
|
||||
|
||||
private void notUpToDateWithChangeToProperty(String name) {
|
||||
assertThat(this.gradleBuild.build("buildInfo", "--stacktrace").task(":buildInfo")
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("buildInfo", "-P" + name + "=changed")
|
||||
.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties() {
|
||||
File file = new File(this.gradleBuild.getProjectDir(),
|
||||
"build/build-info.properties");
|
||||
assertThat(file).isFile();
|
||||
Properties properties = new Properties();
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
properties.load(reader);
|
||||
return properties;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.testfixtures.ProjectBuilder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link BuildInfo}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BuildInfoTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void basicExecution() {
|
||||
Properties properties = buildInfoProperties(createTask(createProject("test")));
|
||||
assertThat(properties).containsKey("build.time");
|
||||
assertThat(properties).containsEntry("build.artifact", "unspecified");
|
||||
assertThat(properties).containsEntry("build.group", "");
|
||||
assertThat(properties).containsEntry("build.name", "test");
|
||||
assertThat(properties).containsEntry("build.version", "unspecified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customArtifactIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setArtifact("custom");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.artifact", "custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectGroupIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProject().setGroup("com.example");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.group", "com.example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customGroupIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setGroup("com.example");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.group", "com.example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customNameIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setName("Example");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.name", "Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectVersionIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProject().setVersion("1.2.3");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.version", "1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customVersionIsReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setVersion("2.3.4");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.version", "2.3.4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalPropertiesAreReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().getAdditional().put("a", "alpha");
|
||||
task.getProperties().getAdditional().put("b", "bravo");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.a", "alpha");
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.b", "bravo");
|
||||
}
|
||||
|
||||
private Project createProject(String projectName) {
|
||||
try {
|
||||
File projectDir = this.temp.newFolder(projectName);
|
||||
return ProjectBuilder.builder().withProjectDir(projectDir)
|
||||
.withName(projectName).build();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private BuildInfo createTask(Project project) {
|
||||
return project.getTasks().create("testBuildInfo", BuildInfo.class);
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties(BuildInfo task) {
|
||||
task.generateBuildProperties();
|
||||
return buildInfoProperties(
|
||||
new File(task.getDestinationDir(), "build-info.properties"));
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties(File file) {
|
||||
assertThat(file).isFile();
|
||||
Properties properties = new Properties();
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
properties.load(reader);
|
||||
return properties;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.gradle.testkit.runner.InvalidRunnerConfigurationException;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.gradle.testkit.runner.UnexpectedBuildFailure;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BootJar}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public abstract class AbstractBootArchiveIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
private final String taskName;
|
||||
|
||||
protected AbstractBootArchiveIntegrationTests(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicBuild() throws InvalidRunnerConfigurationException,
|
||||
UnexpectedBuildFailure, IOException {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upToDateWhenBuiltTwice() throws InvalidRunnerConfigurationException,
|
||||
UnexpectedBuildFailure, IOException {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upToDateWhenBuiltTwiceWithLaunchScriptIncluded()
|
||||
throws InvalidRunnerConfigurationException, UnexpectedBuildFailure,
|
||||
IOException {
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName)
|
||||
.task(":" + this.taskName).getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName)
|
||||
.task(":" + this.taskName).getOutcome())
|
||||
.isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded() {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName)
|
||||
.task(":" + this.taskName).getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded() {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName)
|
||||
.task(":" + this.taskName).getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenLaunchScriptPropertyChanges() {
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true",
|
||||
"-PlaunchScriptProperty=foo", this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("-PincludeLaunchScript=true",
|
||||
"-PlaunchScriptProperty=bar", this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginMainClassNameIsUsed() throws IOException {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
try (JarFile jarFile = new JarFile(
|
||||
new File(this.gradleBuild.getProjectDir(), "build/libs")
|
||||
.listFiles()[0])) {
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.CustomMain");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicatesAreHandledGracefully() throws IOException {
|
||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName)
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
|
||||
import org.gradle.api.tasks.bundling.Jar;
|
||||
import org.gradle.testfixtures.ProjectBuilder;
|
||||
import org.gradle.util.GUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import org.springframework.boot.loader.tools.DefaultLaunchScript;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Abstract base class for testing {@link BootArchive} implementations.
|
||||
*
|
||||
* @param <T> the type of the concrete BootArchive implementation
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||
|
||||
@Rule
|
||||
public final TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
private final Class<T> taskClass;
|
||||
|
||||
private final String launcherClass;
|
||||
|
||||
private final String libPath;
|
||||
|
||||
private final String classesPath;
|
||||
|
||||
private T task;
|
||||
|
||||
protected AbstractBootArchiveTests(Class<T> taskClass, String launcherClass,
|
||||
String libPath, String classesPath) {
|
||||
this.taskClass = taskClass;
|
||||
this.launcherClass = launcherClass;
|
||||
this.libPath = libPath;
|
||||
this.classesPath = classesPath;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void createTask() {
|
||||
try {
|
||||
Project project = ProjectBuilder.builder()
|
||||
.withProjectDir(this.temp.newFolder()).build();
|
||||
this.task = configure(
|
||||
project.getTasks().create("testArchive", this.taskClass));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicArchiveCreation() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Main-Class"))
|
||||
.isEqualTo(this.launcherClass);
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.Main");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classpathJarsArePackagedBeneathLibPath() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
|
||||
this.task.execute();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNotNull();
|
||||
assertThat(jarFile.getEntry(this.libPath + "/two.jar")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classpathFoldersArePackagedBeneathClassesPath() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
File classpathFolder = this.temp.newFolder();
|
||||
File applicationClass = new File(classpathFolder,
|
||||
"com/example/Application.class");
|
||||
applicationClass.getParentFile().mkdirs();
|
||||
applicationClass.createNewFile();
|
||||
this.task.classpath(classpathFolder);
|
||||
this.task.execute();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(
|
||||
jarFile.getEntry(this.classesPath + "/com/example/Application.class"))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loaderIsWrittenToTheRootOfTheJar() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.execute();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(
|
||||
"org/springframework/boot/loader/LaunchedURLClassLoader.class"))
|
||||
.isNotNull();
|
||||
assertThat(jarFile.getEntry("org/springframework/boot/loader/")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loaderIsWrittenToTheRootOfTheJarWhenUsingThePropertiesLauncher()
|
||||
throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.execute();
|
||||
this.task.getManifest().getAttributes().put("Main-Class",
|
||||
"org.springframework.boot.loader.PropertiesLauncher");
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(
|
||||
"org/springframework/boot/loader/LaunchedURLClassLoader.class"))
|
||||
.isNotNull();
|
||||
assertThat(jarFile.getEntry("org/springframework/boot/loader/")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unpackCommentIsAddedToEntryIdentifiedByAPattern() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
|
||||
this.task.requiresUnpack("**/one.jar");
|
||||
this.task.execute();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(this.libPath + "/one.jar").getComment())
|
||||
.startsWith("UNPACK:");
|
||||
assertThat(jarFile.getEntry(this.libPath + "/two.jar").getComment()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unpackCommentIsAddedToEntryIdentifiedByASpec() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
|
||||
this.task.requiresUnpack((element) -> element.getName().endsWith("two.jar"));
|
||||
this.task.execute();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(this.libPath + "/two.jar").getComment())
|
||||
.startsWith("UNPACK:");
|
||||
assertThat(jarFile.getEntry(this.libPath + "/one.jar").getComment()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchScriptCanBePrepended() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.launchScript();
|
||||
this.task.execute();
|
||||
assertThat(Files.readAllBytes(this.task.getArchivePath().toPath()))
|
||||
.startsWith(new DefaultLaunchScript(null, null).toByteArray());
|
||||
try {
|
||||
Set<PosixFilePermission> permissions = Files
|
||||
.getPosixFilePermissions(this.task.getArchivePath().toPath());
|
||||
assertThat(permissions).contains(PosixFilePermission.OWNER_EXECUTE);
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// Windows, presumably. Continue
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customLaunchScriptCanBePrepended() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
File customScript = this.temp.newFile("custom.script");
|
||||
Files.write(customScript.toPath(), Arrays.asList("custom script"),
|
||||
StandardOpenOption.CREATE);
|
||||
this.task.launchScript((configuration) -> configuration.setScript(customScript));
|
||||
this.task.execute();
|
||||
assertThat(Files.readAllBytes(this.task.getArchivePath().toPath()))
|
||||
.startsWith("custom script".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchScriptPropertiesAreReplaced() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.launchScript((configuration) -> configuration.getProperties()
|
||||
.put("initInfoProvides", "test property value"));
|
||||
this.task.execute();
|
||||
assertThat(Files.readAllBytes(this.task.getArchivePath().toPath()))
|
||||
.containsSequence("test property value".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customMainClassInTheManifestIsHonored() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.getManifest().getAttributes().put("Main-Class",
|
||||
"com.example.CustomLauncher");
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Main-Class"))
|
||||
.isEqualTo("com.example.CustomLauncher");
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.Main");
|
||||
assertThat(jarFile.getEntry(
|
||||
"org/springframework/boot/loader/LaunchedURLClassLoader.class"))
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customStartClassInTheManifestIsHonored() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.getManifest().getAttributes().put("Start-Class",
|
||||
"com.example.CustomMain");
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Main-Class"))
|
||||
.isEqualTo(this.launcherClass);
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class"))
|
||||
.isEqualTo("com.example.CustomMain");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileTimestampPreservationCanBeDisabled() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.setPreserveFileTimestamps(false);
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
assertThat(entry.getTime())
|
||||
.isEqualTo(GUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reproducibleOrderingCanBeEnabled() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.from(this.temp.newFile("bravo.txt"), this.temp.newFile("alpha.txt"),
|
||||
this.temp.newFile("charlie.txt"));
|
||||
this.task.setReproducibleFileOrder(true);
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
List<String> textFiles = new ArrayList<>();
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getName().endsWith(".txt")) {
|
||||
textFiles.add(entry.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
assertThat(textFiles).containsExactly("alpha.txt", "bravo.txt", "charlie.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void devtoolsJarIsExcludedByDefault() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.classpath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(this.libPath + "/spring-boot-devtools-0.1.2.jar"))
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void devtoolsJarCanBeIncluded() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.classpath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
|
||||
this.task.setExcludeDevtools(false);
|
||||
this.task.execute();
|
||||
assertThat(this.task.getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
|
||||
assertThat(jarFile.getEntry(this.libPath + "/spring-boot-devtools-0.1.2.jar"))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allEntriesUseUnixPlatformAndUtf8NameEncoding() throws IOException {
|
||||
this.task.setMainClass("com.example.Main");
|
||||
this.task.setMetadataCharset("UTF-8");
|
||||
File classpathFolder = this.temp.newFolder();
|
||||
File resource = new File(classpathFolder, "some-resource.xml");
|
||||
resource.getParentFile().mkdirs();
|
||||
resource.createNewFile();
|
||||
this.task.classpath(classpathFolder);
|
||||
this.task.execute();
|
||||
File archivePath = this.task.getArchivePath();
|
||||
try (ZipFile zip = new ZipFile(archivePath)) {
|
||||
Enumeration<ZipArchiveEntry> entries = zip.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
assertThat(entry.getPlatform()).isEqualTo(ZipArchiveEntry.PLATFORM_UNIX);
|
||||
assertThat(entry.getGeneralPurposeBit().usesUTF8ForNames()).isTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private T configure(T task) throws IOException {
|
||||
AbstractArchiveTask archiveTask = task;
|
||||
archiveTask.setBaseName("test");
|
||||
archiveTask.setDestinationDir(this.temp.newFolder());
|
||||
return task;
|
||||
}
|
||||
|
||||
protected T getTask() {
|
||||
return this.task;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BootJar}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
|
||||
|
||||
public BootJarIntegrationTests() {
|
||||
super("bootJar");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
/**
|
||||
* Tests for {@link BootJar}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BootJarTests extends AbstractBootArchiveTests<BootJar> {
|
||||
|
||||
public BootJarTests() {
|
||||
super(BootJar.class, "org.springframework.boot.loader.JarLauncher",
|
||||
"BOOT-INF/lib", "BOOT-INF/classes");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BootJar}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BootWarIntegrationTests extends AbstractBootArchiveIntegrationTests {
|
||||
|
||||
public BootWarIntegrationTests() {
|
||||
super("bootWar");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link BootWar}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class BootWarTests extends AbstractBootArchiveTests<BootWar> {
|
||||
|
||||
public BootWarTests() {
|
||||
super(BootWar.class, "org.springframework.boot.loader.WarLauncher", "WEB-INF/lib",
|
||||
"WEB-INF/classes");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void providedClasspathJarsArePackagedInWebInfLibProvided() throws IOException {
|
||||
getTask().setMainClass("com.example.Main");
|
||||
getTask().providedClasspath(this.temp.newFile("one.jar"),
|
||||
this.temp.newFile("two.jar"));
|
||||
getTask().execute();
|
||||
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
|
||||
assertThat(jarFile.getEntry("WEB-INF/lib-provided/one.jar")).isNotNull();
|
||||
assertThat(jarFile.getEntry("WEB-INF/lib-provided/two.jar")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void devtoolsJarIsExcludedByDefaultWhenItsOnTheProvidedClasspath()
|
||||
throws IOException {
|
||||
getTask().setMainClass("com.example.Main");
|
||||
getTask().providedClasspath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
|
||||
getTask().execute();
|
||||
assertThat(getTask().getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
|
||||
assertThat(jarFile
|
||||
.getEntry("WEB-INF/lib-provided/spring-boot-devtools-0.1.2.jar"))
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void devtoolsJarCanBeIncludedWhenItsOnTheProvidedClasspath()
|
||||
throws IOException {
|
||||
getTask().setMainClass("com.example.Main");
|
||||
getTask().providedClasspath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
|
||||
getTask().setExcludeDevtools(false);
|
||||
getTask().execute();
|
||||
assertThat(getTask().getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
|
||||
assertThat(jarFile
|
||||
.getEntry("WEB-INF/lib-provided/spring-boot-devtools-0.1.2.jar"))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webappResourcesInDirectoriesThatOverlapWithLoaderCanBePackaged()
|
||||
throws IOException {
|
||||
File webappFolder = this.temp.newFolder("src", "main", "webapp");
|
||||
File orgFolder = new File(webappFolder, "org");
|
||||
orgFolder.mkdir();
|
||||
new File(orgFolder, "foo.txt").createNewFile();
|
||||
getTask().from(webappFolder);
|
||||
getTask().setMainClass("com.example.Main");
|
||||
getTask().execute();
|
||||
assertThat(getTask().getArchivePath().exists());
|
||||
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
|
||||
assertThat(jarFile.getEntry("org/")).isNotNull();
|
||||
assertThat(jarFile.getEntry("org/foo.txt")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for uploading Boot jars and wars using Gradle's Maven plugin.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class MavenIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void bootJarCanBeUploaded() throws FileNotFoundException, IOException {
|
||||
BuildResult result = this.gradleBuild.build("uploadBootArchives");
|
||||
assertThat(result.task(":uploadBootArchives").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(artifactWithSuffix("jar")).isFile();
|
||||
assertThat(artifactWithSuffix("pom")).is(pomWith().groupId("com.example")
|
||||
.artifactId(this.gradleBuild.getProjectDir().getName()).version("1.0")
|
||||
.noPackaging().noDependencies());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootWarCanBeUploaded() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build("uploadBootArchives");
|
||||
assertThat(result.task(":uploadBootArchives").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(artifactWithSuffix("war")).isFile();
|
||||
assertThat(artifactWithSuffix("pom")).is(pomWith().groupId("com.example")
|
||||
.artifactId(this.gradleBuild.getProjectDir().getName()).version("1.0")
|
||||
.packaging("war").noDependencies());
|
||||
}
|
||||
|
||||
private File artifactWithSuffix(String suffix) {
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
return new File(new File(this.gradleBuild.getProjectDir(), "build/repo"),
|
||||
String.format("com/example/%s/1.0/%s-1.0.%s", name, name, suffix));
|
||||
}
|
||||
|
||||
private PomCondition pomWith() {
|
||||
return new PomCondition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for publishing Boot jars and wars using Gradle's Maven Publish
|
||||
* plugin.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class MavenPublishingIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void bootJarCanBePublished() throws FileNotFoundException, IOException {
|
||||
BuildResult result = this.gradleBuild.build("publish");
|
||||
assertThat(result.task(":publish").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(artifactWithSuffix("jar")).isFile();
|
||||
assertThat(artifactWithSuffix("pom")).is(pomWith().groupId("com.example")
|
||||
.artifactId(this.gradleBuild.getProjectDir().getName()).version("1.0")
|
||||
.noPackaging().noDependencies());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootWarCanBePublished() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build("publish");
|
||||
assertThat(result.task(":publish").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(artifactWithSuffix("war")).isFile();
|
||||
assertThat(artifactWithSuffix("pom")).is(pomWith().groupId("com.example")
|
||||
.artifactId(this.gradleBuild.getProjectDir().getName()).version("1.0")
|
||||
.packaging("war").noDependencies());
|
||||
}
|
||||
|
||||
private File artifactWithSuffix(String suffix) {
|
||||
String name = this.gradleBuild.getProjectDir().getName();
|
||||
return new File(new File(this.gradleBuild.getProjectDir(), "build/repo"),
|
||||
String.format("com/example/%s/1.0/%s-1.0.%s", name, name, suffix));
|
||||
}
|
||||
|
||||
private PomCondition pomWith() {
|
||||
return new PomCondition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.assertj.core.description.Description;
|
||||
import org.assertj.core.description.TextDescription;
|
||||
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* AssertJ {@link Condition} for asserting the contents of a pom file.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class PomCondition extends Condition<File> {
|
||||
|
||||
private Set<String> expectedContents;
|
||||
|
||||
private Set<String> notExpectedContents;
|
||||
|
||||
PomCondition() {
|
||||
this(new HashSet<>(), new HashSet<>());
|
||||
}
|
||||
|
||||
private PomCondition(Set<String> expectedContents, Set<String> notExpectedContents) {
|
||||
super(new TextDescription("Pom file containing %s and not containing %s",
|
||||
expectedContents, notExpectedContents));
|
||||
this.expectedContents = expectedContents;
|
||||
this.notExpectedContents = notExpectedContents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(File pom) {
|
||||
try {
|
||||
String contents = FileCopyUtils.copyToString(new FileReader(pom));
|
||||
for (String expected : this.expectedContents) {
|
||||
if (!contents.contains(expected)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (String notExpected : this.notExpectedContents) {
|
||||
if (contents.contains(notExpected)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description description() {
|
||||
return new TextDescription("Pom file containing %s and not containing %s",
|
||||
this.expectedContents, this.notExpectedContents);
|
||||
}
|
||||
|
||||
PomCondition groupId(String groupId) {
|
||||
this.expectedContents.add(String.format("<groupId>%s</groupId>", groupId));
|
||||
return this;
|
||||
}
|
||||
|
||||
PomCondition artifactId(String artifactId) {
|
||||
this.expectedContents
|
||||
.add(String.format("<artifactId>%s</artifactId>", artifactId));
|
||||
return this;
|
||||
}
|
||||
|
||||
PomCondition version(String version) {
|
||||
this.expectedContents.add(String.format("<version>%s</version>", version));
|
||||
return this;
|
||||
}
|
||||
|
||||
PomCondition packaging(String packaging) {
|
||||
this.expectedContents.add(String.format("<packaging>%s</packaging>", packaging));
|
||||
return this;
|
||||
}
|
||||
|
||||
PomCondition noDependencies() {
|
||||
this.notExpectedContents.add("<dependencies>");
|
||||
return this;
|
||||
}
|
||||
|
||||
PomCondition noPackaging() {
|
||||
this.notExpectedContents.add("<packaging>");
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.tasks.run;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibilitySuite;
|
||||
import org.springframework.boot.gradle.testkit.GradleBuild;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link BootRun} task.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(GradleCompatibilitySuite.class)
|
||||
public class BootRunIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public GradleBuild gradleBuild;
|
||||
|
||||
@Test
|
||||
public void basicExecution() throws IOException {
|
||||
copyApplication();
|
||||
new File(this.gradleBuild.getProjectDir(), "src/main/resources").mkdirs();
|
||||
BuildResult result = this.gradleBuild.build("bootRun");
|
||||
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput())
|
||||
.contains("1. " + canonicalPathOf("build/classes/java/main"));
|
||||
assertThat(result.getOutput())
|
||||
.contains("2. " + canonicalPathOf("build/resources/main"));
|
||||
assertThat(result.getOutput())
|
||||
.doesNotContain(canonicalPathOf("src/main/resources"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void argsCanBeConfigured() throws IOException {
|
||||
copyApplication();
|
||||
new File(this.gradleBuild.getProjectDir(), "src/main/resources").mkdirs();
|
||||
BuildResult result = this.gradleBuild.build("bootRun");
|
||||
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).contains("--com.example.foo=bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jvmArgsCanBeConfigured() throws IOException {
|
||||
copyApplication();
|
||||
new File(this.gradleBuild.getProjectDir(), "src/main/resources").mkdirs();
|
||||
BuildResult result = this.gradleBuild.build("bootRun");
|
||||
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).contains("-Dcom.example.foo=bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void execSpecCanBeConfigured() throws IOException {
|
||||
copyApplication();
|
||||
new File(this.gradleBuild.getProjectDir(), "src/main/resources").mkdirs();
|
||||
BuildResult result = this.gradleBuild.build("bootRun");
|
||||
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).contains("-Dcom.example.foo=bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceResourcesCanBeUsed() throws IOException {
|
||||
copyApplication();
|
||||
BuildResult result = this.gradleBuild.build("bootRun");
|
||||
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput())
|
||||
.contains("1. " + canonicalPathOf("src/main/resources"));
|
||||
assertThat(result.getOutput())
|
||||
.contains("2. " + canonicalPathOf("build/classes/java/main"));
|
||||
assertThat(result.getOutput())
|
||||
.doesNotContain(canonicalPathOf("build/resources/main"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginMainClassNameIsUsed() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build("echoMainClassName");
|
||||
assertThat(result.task(":echoMainClassName").getOutcome())
|
||||
.isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
assertThat(result.getOutput())
|
||||
.contains("Main class name = com.example.CustomMainClass");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginMainClassNameIsNotUsedWhenItIsNull() throws IOException {
|
||||
copyApplication();
|
||||
BuildResult result = this.gradleBuild.build("echoMainClassName");
|
||||
assertThat(result.task(":echoMainClassName").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput())
|
||||
.contains("Main class name = com.example.BootRunApplication");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationPluginJvmArgumentsAreUsed() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build("echoJvmArguments");
|
||||
assertThat(result.task(":echoJvmArguments").getOutcome())
|
||||
.isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
assertThat(result.getOutput())
|
||||
.contains("JVM arguments = [-Dcom.foo=bar, -Dcom.bar=baz]");
|
||||
}
|
||||
|
||||
private void copyApplication() throws IOException {
|
||||
File output = new File(this.gradleBuild.getProjectDir(),
|
||||
"src/main/java/com/example");
|
||||
output.mkdirs();
|
||||
FileSystemUtils.copyRecursively(new File("src/test/java/com/example"), output);
|
||||
}
|
||||
|
||||
private String canonicalPathOf(String path) throws IOException {
|
||||
return new File(this.gradleBuild.getProjectDir(), path).getCanonicalPath();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.gradle.testkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.GradleRunner;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.asm.ClassVisitor;
|
||||
import org.springframework.boot.loader.tools.LaunchScript;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* A {@link TestRule} for running a Gradle build using {@link GradleRunner}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class GradleBuild implements TestRule {
|
||||
|
||||
private final TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
private File projectDir;
|
||||
|
||||
private String script;
|
||||
|
||||
private String gradleVersion;
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
URL scriptUrl = findDefaultScript(description);
|
||||
if (scriptUrl != null) {
|
||||
script(scriptUrl.getFile());
|
||||
}
|
||||
return this.temp.apply(new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
before();
|
||||
try {
|
||||
base.evaluate();
|
||||
}
|
||||
finally {
|
||||
after();
|
||||
}
|
||||
}
|
||||
|
||||
}, description);
|
||||
}
|
||||
|
||||
private URL findDefaultScript(Description description) {
|
||||
URL scriptUrl = getScriptForTestMethod(description);
|
||||
if (scriptUrl != null) {
|
||||
return scriptUrl;
|
||||
}
|
||||
return getScriptForTestClass(description.getTestClass());
|
||||
}
|
||||
|
||||
private URL getScriptForTestMethod(Description description) {
|
||||
String name = description.getTestClass().getSimpleName() + "-"
|
||||
+ removeGradleVersion(description.getMethodName()) + ".gradle";
|
||||
return description.getTestClass().getResource(name);
|
||||
}
|
||||
|
||||
private String removeGradleVersion(String methodName) {
|
||||
return methodName.replaceAll("\\[Gradle .+\\]", "").trim();
|
||||
}
|
||||
|
||||
private URL getScriptForTestClass(Class<?> testClass) {
|
||||
return testClass.getResource(testClass.getSimpleName() + ".gradle");
|
||||
}
|
||||
|
||||
private void before() throws IOException {
|
||||
this.projectDir = this.temp.newFolder();
|
||||
}
|
||||
|
||||
private void after() {
|
||||
GradleBuild.this.script = null;
|
||||
}
|
||||
|
||||
private String pluginClasspath() {
|
||||
return absolutePath("bin") + "," + absolutePath("build/classes/java/main") + ","
|
||||
+ absolutePath("build/resources/main") + ","
|
||||
+ pathOfJarContaining(LaunchScript.class) + ","
|
||||
+ pathOfJarContaining(ClassVisitor.class) + ","
|
||||
+ pathOfJarContaining(DependencyManagementPlugin.class) + ","
|
||||
+ pathOfJarContaining(ArchiveEntry.class);
|
||||
}
|
||||
|
||||
private String absolutePath(String path) {
|
||||
return new File(path).getAbsolutePath();
|
||||
}
|
||||
|
||||
private String pathOfJarContaining(Class<?> type) {
|
||||
return type.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
}
|
||||
|
||||
public GradleBuild script(String script) {
|
||||
this.script = script;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuildResult build(String... arguments) {
|
||||
try {
|
||||
return prepareRunner(arguments).build();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public BuildResult buildAndFail(String... arguments) {
|
||||
try {
|
||||
return prepareRunner(arguments).buildAndFail();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public GradleRunner prepareRunner(String... arguments) throws IOException {
|
||||
String scriptContent = FileCopyUtils.copyToString(new FileReader(this.script))
|
||||
.replace("{version}", getBootVersion());
|
||||
FileCopyUtils.copy(scriptContent,
|
||||
new FileWriter(new File(this.projectDir, "build.gradle")));
|
||||
GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir)
|
||||
.withDebug(true);
|
||||
if (this.gradleVersion != null) {
|
||||
gradleRunner.withGradleVersion(this.gradleVersion);
|
||||
}
|
||||
List<String> allArguments = new ArrayList<>();
|
||||
allArguments.add("-PpluginClasspath=" + pluginClasspath());
|
||||
allArguments.add("-PbootVersion=" + getBootVersion());
|
||||
allArguments.add("--stacktrace");
|
||||
allArguments.addAll(Arrays.asList(arguments));
|
||||
return gradleRunner.withArguments(allArguments);
|
||||
}
|
||||
|
||||
public File getProjectDir() {
|
||||
return this.projectDir;
|
||||
}
|
||||
|
||||
public void setProjectDir(File projectDir) {
|
||||
this.projectDir = projectDir;
|
||||
}
|
||||
|
||||
public GradleBuild gradleVersion(String version) {
|
||||
this.gradleVersion = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getGradleVersion() {
|
||||
return this.gradleVersion;
|
||||
}
|
||||
|
||||
private static String getBootVersion() {
|
||||
return evaluateExpression(
|
||||
"/*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']"
|
||||
+ "/text()");
|
||||
}
|
||||
|
||||
private static String evaluateExpression(String expression) {
|
||||
try {
|
||||
XPathFactory xPathFactory = XPathFactory.newInstance();
|
||||
XPath xpath = xPathFactory.newXPath();
|
||||
XPathExpression expr = xpath.compile(expression);
|
||||
String version = expr.evaluate(new InputSource(new FileReader("pom.xml")));
|
||||
return version;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to evaluate expression", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
group = 'com.example'
|
||||
version = '1.0'
|
||||
|
||||
springBoot {
|
||||
buildInfo {
|
||||
properties {
|
||||
additionalProperties = [
|
||||
'a': 'alpha', 'b': 'bravo'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
group = 'com.example'
|
||||
version = '1.0'
|
||||
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'war'
|
||||
|
||||
group = 'com.example'
|
||||
version = '1.0'
|
||||
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'java'
|
||||
|
||||
group = 'com.example'
|
||||
version = '1.0'
|
||||
|
||||
bootJar {
|
||||
baseName = 'foo'
|
||||
}
|
||||
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath files(pluginClasspath.split(','))
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'war'
|
||||
|
||||
group = 'com.example'
|
||||
version = '1.0'
|
||||
|
||||
bootWar {
|
||||
baseName = 'foo'
|
||||
}
|
||||
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user