From 00faf445547d0047fe28d9b892a2e9ba75f81b66 Mon Sep 17 00:00:00 2001 From: Steve Riesenberg Date: Wed, 30 Mar 2022 15:04:56 -0500 Subject: [PATCH] Add buildSrc with migrated conventions plugins --- buildSrc/build.gradle | 27 +++-- .../gradle/docs/SpringDeployDocsPlugin.groovy | 78 +++++++++++++ .../gradle/convention/SpringDocsPlugin.java | 71 ++++++++++++ .../gradle/convention/SpringModulePlugin.java | 41 +++++++ .../convention/SpringRootProjectPlugin.java | 46 ++++++++ .../src/main/java/lock/GlobalLockPlugin.java | 16 --- .../src/main/java/lock/GlobalLockTask.java | 40 ------- .../springframework/gradle/ProjectUtils.java | 53 +++++++++ .../gradle/SpringJavaPlugin.java | 96 ++++++++++++++++ .../gradle/SpringMavenPlugin.java | 48 ++++++++ .../SpringJavaCheckstylePlugin.java | 86 ++++++++++++++ ...eckClasspathForProhibitedDependencies.java | 100 ++++++++++++++++ ...sspathForProhibitedDependenciesPlugin.java | 67 +++++++++++ ...ProhibitedDependenciesLifecyclePlugin.java | 41 +++++++ .../gradle/docs/SpringJavadocApiPlugin.java | 108 ++++++++++++++++++ .../docs/SpringJavadocOptionsPlugin.java | 35 ++++++ .../gradle/jacoco/SpringJacocoPlugin.java | 56 +++++++++ .../SpringManagementConfigurationPlugin.java | 67 +++++++++++ .../gradle/maven/SpringArtifactoryPlugin.java | 56 +++++++++ ...pringMavenPublishingConventionsPlugin.java | 106 +++++++++++++++++ .../gradle/maven/SpringNexusPlugin.java | 57 +++++++++ .../SpringPublishAllJavaComponentsPlugin.java | 43 +++++++ .../maven/SpringPublishArtifactsPlugin.java | 40 +++++++ .../maven/SpringPublishLocalPlugin.java | 40 +++++++ .../gradle/maven/SpringRepositoryPlugin.java | 71 ++++++++++++ .../gradle/maven/SpringSigningPlugin.java | 61 ++++++++++ .../gradle/nohttp/SpringNoHttpPlugin.java | 41 +++++++ .../propdeps/SpringPropDepsEclipsePlugin.java | 47 ++++++++ .../propdeps/SpringPropDepsIdeaPlugin.java | 50 ++++++++ .../gradle/propdeps/SpringPropDepsPlugin.java | 80 +++++++++++++ .../SpringCopyPropertiesPlugin.java | 40 +++++++ .../sonarqube/SpringSonarQubePlugin.java | 49 ++++++++ .../io.spring.convention.docs.properties | 1 + .../io.spring.convention.root.properties | 1 + ...spring.convention.spring-module.properties | 1 + ...ingframework.gradle.deploy-docs.properties | 2 + 36 files changed, 1798 insertions(+), 64 deletions(-) create mode 100644 buildSrc/src/main/groovy/org/springframework/gradle/docs/SpringDeployDocsPlugin.groovy create mode 100644 buildSrc/src/main/java/io/spring/gradle/convention/SpringDocsPlugin.java create mode 100644 buildSrc/src/main/java/io/spring/gradle/convention/SpringModulePlugin.java create mode 100644 buildSrc/src/main/java/io/spring/gradle/convention/SpringRootProjectPlugin.java delete mode 100644 buildSrc/src/main/java/lock/GlobalLockPlugin.java delete mode 100644 buildSrc/src/main/java/lock/GlobalLockTask.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/ProjectUtils.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/SpringJavaPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/SpringMavenPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/checkstyle/SpringJavaCheckstylePlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependencies.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckClasspathForProhibitedDependenciesPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckProhibitedDependenciesLifecyclePlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocApiPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocOptionsPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/jacoco/SpringJacocoPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/management/SpringManagementConfigurationPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringArtifactoryPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringMavenPublishingConventionsPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringNexusPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishAllJavaComponentsPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishArtifactsPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishLocalPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringRepositoryPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/maven/SpringSigningPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/nohttp/SpringNoHttpPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsEclipsePlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsIdeaPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/properties/SpringCopyPropertiesPlugin.java create mode 100644 buildSrc/src/main/java/org/springframework/gradle/sonarqube/SpringSonarQubePlugin.java create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.docs.properties create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.root.properties create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.spring-module.properties create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/org.springframework.gradle.deploy-docs.properties diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 5e9de25d..3d558acc 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,14 +1,25 @@ -apply plugin: "java-gradle-plugin" +plugins { + id "java-gradle-plugin" + id "java" + id "groovy" +} + +sourceCompatibility = JavaVersion.VERSION_11 repositories { + gradlePluginPortal() mavenCentral() + maven { url "https://repo.spring.io/plugins-release/" } } -gradlePlugin { - plugins { - locks { - id = "locks" - implementationClass = "lock.GlobalLockPlugin" - } - } +dependencies { + implementation "com.github.ben-manes:gradle-versions-plugin:0.38.0" + implementation "io.github.gradle-nexus:publish-plugin:1.1.0" + implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.31" + implementation "io.spring.nohttp:nohttp-gradle:0.0.10" + implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10" + implementation "org.hidetake:gradle-ssh-plugin:2.10.1" + implementation "org.jfrog.buildinfo:build-info-extractor-gradle:4.26.1" + implementation "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1" + implementation "org.springframework:spring-core:5.3.17" } diff --git a/buildSrc/src/main/groovy/org/springframework/gradle/docs/SpringDeployDocsPlugin.groovy b/buildSrc/src/main/groovy/org/springframework/gradle/docs/SpringDeployDocsPlugin.groovy new file mode 100644 index 00000000..8ad17d97 --- /dev/null +++ b/buildSrc/src/main/groovy/org/springframework/gradle/docs/SpringDeployDocsPlugin.groovy @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.docs + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class SpringDeployDocsPlugin implements Plugin { + + @Override + void apply(Project project) { + project.getPluginManager().apply('org.hidetake.ssh') + + project.ssh.settings { + knownHosts = allowAnyHosts + } + project.remotes { + docs { + role 'docs' + if (project.hasProperty('deployDocsHost')) { + host = project.findProperty('deployDocsHost') + } + retryCount = 5 // retry 5 times (default is 0) + retryWaitSec = 10 // wait 10 seconds between retries (default is 0) + user = project.findProperty('deployDocsSshUsername') + if (project.hasProperty('deployDocsSshKeyPath')) { + identity = project.file(project.findProperty('deployDocsSshKeyPath')) + } else if (project.hasProperty('deployDocsSshKey')) { + identity = project.findProperty('deployDocsSshKey') + } + if (project.hasProperty('deployDocsSshPassphrase')) { + passphrase = project.findProperty('deployDocsSshPassphrase') + } + } + } + + project.task('deployDocs') { + dependsOn 'docsZip' + doFirst { + project.ssh.run { + session(project.remotes.docs) { + def now = System.currentTimeMillis() + def name = project.rootProject.name + def version = project.rootProject.version + def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_') + execute "mkdir -p $tempPath" + + project.tasks.docsZip.outputs.each { o -> + put from: o.files, into: tempPath + } + + execute "unzip $tempPath*.zip -d $tempPath" + + def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/docs/${name}/${version}/" + + execute "rm -rf $extractPath" + execute "mkdir -p $extractPath" + execute "mv $tempPath/docs/* $extractPath" + execute "chmod -R g+w $extractPath" + } + } + } + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/java/io/spring/gradle/convention/SpringDocsPlugin.java b/buildSrc/src/main/java/io/spring/gradle/convention/SpringDocsPlugin.java new file mode 100644 index 00000000..9c6ed0b4 --- /dev/null +++ b/buildSrc/src/main/java/io/spring/gradle/convention/SpringDocsPlugin.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2022 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 + * + * https://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 io.spring.gradle.convention; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.DuplicatesStrategy; +import org.gradle.api.plugins.BasePlugin; +import org.gradle.api.plugins.PluginManager; +import org.gradle.api.tasks.TaskContainer; +import org.gradle.api.tasks.bundling.Zip; + +import org.springframework.gradle.docs.SpringJavadocApiPlugin; +import org.springframework.gradle.docs.SpringJavadocOptionsPlugin; + +/** + * Aggregates asciidoc, javadoc, and deploying of the docs into a single plugin. + * + * @author Steve Riesenberg + */ +public class SpringDocsPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply default plugins + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(BasePlugin.class); + // Note: Applying plugin via id since it requires groovy compilation + pluginManager.apply("org.springframework.gradle.deploy-docs"); + pluginManager.apply(SpringJavadocApiPlugin.class); + pluginManager.apply(SpringJavadocOptionsPlugin.class); + + // Add task to create documentation archive + TaskContainer tasks = project.getTasks(); + Zip docsZip = tasks.create("docsZip", Zip.class, (zip) -> { + zip.dependsOn(tasks.getByName("api")); + zip.setGroup("Distribution"); + zip.getArchiveBaseName().set(project.getRootProject().getName()); + zip.getArchiveClassifier().set("docs"); + zip.setDescription("Builds -docs archive containing all " + + "Docs for deployment at docs.spring.io"); + + zip.from(tasks.getByName("api").getOutputs(), (copy) -> copy.into("api")); + zip.into("docs"); + zip.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE); + }); + + // Add task to aggregate documentation + Task docs = tasks.create("docs"); + docs.dependsOn(docsZip); + docs.setGroup("Documentation"); + docs.setDescription("An aggregator task to generate all the documentation"); + + // Wire docs task into the build + tasks.getByName("assemble").dependsOn(docs); + } +} diff --git a/buildSrc/src/main/java/io/spring/gradle/convention/SpringModulePlugin.java b/buildSrc/src/main/java/io/spring/gradle/convention/SpringModulePlugin.java new file mode 100644 index 00000000..821c392f --- /dev/null +++ b/buildSrc/src/main/java/io/spring/gradle/convention/SpringModulePlugin.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2022 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 + * + * https://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 io.spring.gradle.convention; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaLibraryPlugin; +import org.gradle.api.plugins.PluginManager; + +import org.springframework.gradle.SpringJavaPlugin; +import org.springframework.gradle.SpringMavenPlugin; +import org.springframework.gradle.classpath.SpringCheckClasspathForProhibitedDependenciesPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringModulePlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply default plugins + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(JavaLibraryPlugin.class); + pluginManager.apply(SpringJavaPlugin.class); + pluginManager.apply(SpringMavenPlugin.class); + pluginManager.apply(SpringCheckClasspathForProhibitedDependenciesPlugin.class); + } +} diff --git a/buildSrc/src/main/java/io/spring/gradle/convention/SpringRootProjectPlugin.java b/buildSrc/src/main/java/io/spring/gradle/convention/SpringRootProjectPlugin.java new file mode 100644 index 00000000..d9c09639 --- /dev/null +++ b/buildSrc/src/main/java/io/spring/gradle/convention/SpringRootProjectPlugin.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2022 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 + * + * https://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 io.spring.gradle.convention; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.BasePlugin; +import org.gradle.api.plugins.PluginManager; + +import org.springframework.gradle.classpath.SpringCheckProhibitedDependenciesLifecyclePlugin; +import org.springframework.gradle.maven.SpringNexusPlugin; +import org.springframework.gradle.nohttp.SpringNoHttpPlugin; +import org.springframework.gradle.sonarqube.SpringSonarQubePlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringRootProjectPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply default plugins + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(BasePlugin.class); + pluginManager.apply(SpringNoHttpPlugin.class); + pluginManager.apply(SpringNexusPlugin.class); + pluginManager.apply(SpringCheckProhibitedDependenciesLifecyclePlugin.class); + pluginManager.apply(SpringSonarQubePlugin.class); + + // Apply default repositories + project.getRepositories().mavenCentral(); + } +} diff --git a/buildSrc/src/main/java/lock/GlobalLockPlugin.java b/buildSrc/src/main/java/lock/GlobalLockPlugin.java deleted file mode 100644 index 955e73e6..00000000 --- a/buildSrc/src/main/java/lock/GlobalLockPlugin.java +++ /dev/null @@ -1,16 +0,0 @@ -package lock; - -import org.gradle.api.Plugin; -import org.gradle.api.Project; - -/** - * @author Rob Winch - */ -public class GlobalLockPlugin implements Plugin { - @Override - public void apply(Project project) { - project.getTasks().register("writeLocks", GlobalLockTask.class, writeAll -> { - writeAll.setDescription("Writes the locks for all projects"); - }); - } -} diff --git a/buildSrc/src/main/java/lock/GlobalLockTask.java b/buildSrc/src/main/java/lock/GlobalLockTask.java deleted file mode 100644 index 20a8f8f1..00000000 --- a/buildSrc/src/main/java/lock/GlobalLockTask.java +++ /dev/null @@ -1,40 +0,0 @@ -package lock; - -import org.gradle.api.Action; -import org.gradle.api.DefaultTask; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; -import org.gradle.api.tasks.TaskAction; - -import java.util.function.Consumer; - -/** - * @author Rob Winch - */ -public class GlobalLockTask extends DefaultTask { - @TaskAction - public void lock() { - Project taskProject = getProject(); - if (!taskProject.getGradle().getStartParameter().isWriteDependencyLocks()) { - throw new IllegalStateException("You just specify --write-locks argument"); - } - writeLocksFor(taskProject); - taskProject.getSubprojects().forEach(new Consumer() { - @Override - public void accept(Project subproject) { - writeLocksFor(subproject); - } - }); - } - - private void writeLocksFor(Project project) { - project.getConfigurations().configureEach(new Action() { - @Override - public void execute(Configuration configuration) { - if (configuration.isCanBeResolved()) { - configuration.resolve(); - } - } - }); - } -} diff --git a/buildSrc/src/main/java/org/springframework/gradle/ProjectUtils.java b/buildSrc/src/main/java/org/springframework/gradle/ProjectUtils.java new file mode 100644 index 00000000..5f62b293 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/ProjectUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle; + +import org.gradle.api.Project; + +/** + * @author Steve Riesenberg + */ +public class ProjectUtils { + private ProjectUtils() { + } + + public static String getProjectName(Project project) { + String projectName = project.getRootProject().getName(); + if (projectName.endsWith("-build")) { + projectName = projectName.substring(0, projectName.length() - "-build".length()); + } + return projectName; + } + + public static boolean isSnapshot(Project project) { + String projectVersion = projectVersion(project); + return projectVersion.matches("^.*([.-]BUILD)?-SNAPSHOT$"); + } + + public static boolean isMilestone(Project project) { + String projectVersion = projectVersion(project); + return projectVersion.matches("^.*[.-]M\\d+$") || projectVersion.matches("^.*[.-]RC\\d+$"); + } + + public static boolean isRelease(Project project) { + return !(isSnapshot(project) || isMilestone(project)); + } + + private static String projectVersion(Project project) { + return String.valueOf(project.getVersion()); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/SpringJavaPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/SpringJavaPlugin.java new file mode 100644 index 00000000..728562d6 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/SpringJavaPlugin.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle; + +import java.util.HashMap; +import java.util.Map; + +import io.spring.javaformat.gradle.SpringJavaFormatPlugin; +import org.gradle.api.JavaVersion; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.GroovyPlugin; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.plugins.PluginManager; +import org.gradle.api.tasks.compile.CompileOptions; +import org.gradle.api.tasks.compile.JavaCompile; +import org.gradle.api.tasks.testing.Test; +import org.gradle.jvm.tasks.Jar; +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper; + +import org.springframework.gradle.checkstyle.SpringJavaCheckstylePlugin; +import org.springframework.gradle.docs.SpringJavadocOptionsPlugin; +import org.springframework.gradle.jacoco.SpringJacocoPlugin; +import org.springframework.gradle.management.SpringManagementConfigurationPlugin; +import org.springframework.gradle.maven.SpringRepositoryPlugin; +import org.springframework.gradle.propdeps.SpringPropDepsEclipsePlugin; +import org.springframework.gradle.propdeps.SpringPropDepsIdeaPlugin; +import org.springframework.gradle.properties.SpringCopyPropertiesPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringJavaPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply default plugins + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(JavaPlugin.class); + pluginManager.apply(SpringManagementConfigurationPlugin.class); + if (project.file("src/main/groovy").exists() + || project.file("src/test/groovy").exists() + || project.file("src/integration-test/groovy").exists()) { + pluginManager.apply(GroovyPlugin.class); + } + if (project.file("src/main/kotlin").exists() + || project.file("src/test/kotlin").exists() + || project.file("src/integration-test/kotlin").exists() + || project.getBuildFile().getName().endsWith(".kts")) { + pluginManager.apply(KotlinPluginWrapper.class); + } + pluginManager.apply(SpringRepositoryPlugin.class); + pluginManager.apply(SpringPropDepsEclipsePlugin.class); + pluginManager.apply(SpringPropDepsIdeaPlugin.class); + pluginManager.apply(SpringJavadocOptionsPlugin.class); + pluginManager.apply(SpringJavaFormatPlugin.class); + pluginManager.apply(SpringJavaCheckstylePlugin.class); + pluginManager.apply(SpringCopyPropertiesPlugin.class); + pluginManager.apply(SpringJacocoPlugin.class); + + // Apply Java source compatibility version + JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class); + java.setTargetCompatibility(JavaVersion.VERSION_1_8); + + // Configure Java tasks + project.getTasks().withType(JavaCompile.class, (javaCompile) -> { + CompileOptions options = javaCompile.getOptions(); + options.setEncoding("UTF-8"); + options.getCompilerArgs().add("-parameters"); + options.getRelease().set(8); + }); + project.getTasks().withType(Jar.class, (jar) -> jar.manifest((manifest) -> { + Map attributes = new HashMap<>(); + attributes.put("Created-By", String.format("%s (%s)", System.getProperty("java.version"), System.getProperty("java.specification.vendor"))); + attributes.put("Implementation-Title", project.getName()); + attributes.put("Implementation-Version", project.getVersion().toString()); + attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); + manifest.attributes(attributes); + })); + project.getTasks().withType(Test.class, Test::useJUnitPlatform); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/SpringMavenPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/SpringMavenPlugin.java new file mode 100644 index 00000000..c7c8c963 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/SpringMavenPlugin.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.PluginManager; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +import org.springframework.gradle.maven.SpringArtifactoryPlugin; +import org.springframework.gradle.maven.SpringMavenPublishingConventionsPlugin; +import org.springframework.gradle.maven.SpringPublishAllJavaComponentsPlugin; +import org.springframework.gradle.maven.SpringPublishArtifactsPlugin; +import org.springframework.gradle.maven.SpringPublishLocalPlugin; +import org.springframework.gradle.maven.SpringSigningPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringMavenPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply default plugins + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(MavenPublishPlugin.class); + + pluginManager.apply(SpringSigningPlugin.class); + pluginManager.apply(SpringMavenPublishingConventionsPlugin.class); + pluginManager.apply(SpringPublishAllJavaComponentsPlugin.class); + pluginManager.apply(SpringPublishLocalPlugin.class); + pluginManager.apply(SpringPublishArtifactsPlugin.class); + pluginManager.apply(SpringArtifactoryPlugin.class); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/checkstyle/SpringJavaCheckstylePlugin.java b/buildSrc/src/main/java/org/springframework/gradle/checkstyle/SpringJavaCheckstylePlugin.java new file mode 100644 index 00000000..06ef2024 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/checkstyle/SpringJavaCheckstylePlugin.java @@ -0,0 +1,86 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.checkstyle; + +import java.io.File; +import java.util.Objects; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.quality.CheckstyleExtension; +import org.gradle.api.plugins.quality.CheckstylePlugin; + +/** + * Adds and configures Checkstyle plugin. + * + * @author Vedran Pavic + * @author Steve Riesenberg + */ +public class SpringJavaCheckstylePlugin implements Plugin { + private static final String CHECKSTYLE_DIR = "etc/checkstyle"; + private static final String SPRING_JAVAFORMAT_VERSION_PROPERTY = "springJavaformatVersion"; + private static final String DEFAULT_SPRING_JAVAFORMAT_VERSION = "0.0.31"; + private static final String NOHTTP_CHECKSTYLE_VERSION_PROPERTY = "nohttpCheckstyleVersion"; + private static final String DEFAULT_NOHTTP_CHECKSTYLE_VERSION = "0.0.10"; + private static final String CHECKSTYLE_TOOL_VERSION_PROPERTY = "checkstyleToolVersion"; + private static final String DEFAULT_CHECKSTYLE_TOOL_VERSION = "8.34"; + + @Override + public void apply(Project project) { + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { + File checkstyleDir = project.getRootProject().file(CHECKSTYLE_DIR); + if (checkstyleDir.exists() && checkstyleDir.isDirectory()) { + project.getPluginManager().apply(CheckstylePlugin.class); + + // NOTE: See gradle.properties#springJavaformatVersion for actual version number + project.getDependencies().add("checkstyle", "io.spring.javaformat:spring-javaformat-checkstyle:" + getSpringJavaformatVersion(project)); + // NOTE: See gradle.properties#nohttpCheckstyleVersion for actual version number + project.getDependencies().add("checkstyle", "io.spring.nohttp:nohttp-checkstyle:" + getNohttpCheckstyleVersion(project)); + + CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class); + checkstyle.getConfigDirectory().set(checkstyleDir); + // NOTE: See gradle.properties#checkstyleToolVersion for actual version number + checkstyle.setToolVersion(getCheckstyleToolVersion(project)); + } + }); + } + + private static String getSpringJavaformatVersion(Project project) { + String springJavaformatVersion = DEFAULT_SPRING_JAVAFORMAT_VERSION; + if (project.hasProperty(SPRING_JAVAFORMAT_VERSION_PROPERTY)) { + springJavaformatVersion = Objects.requireNonNull(project.findProperty(SPRING_JAVAFORMAT_VERSION_PROPERTY)).toString(); + } + return springJavaformatVersion; + } + + private static String getNohttpCheckstyleVersion(Project project) { + String nohttpCheckstyleVersion = DEFAULT_NOHTTP_CHECKSTYLE_VERSION; + if (project.hasProperty(NOHTTP_CHECKSTYLE_VERSION_PROPERTY)) { + nohttpCheckstyleVersion = Objects.requireNonNull(project.findProperty(NOHTTP_CHECKSTYLE_VERSION_PROPERTY)).toString(); + } + return nohttpCheckstyleVersion; + } + + private static String getCheckstyleToolVersion(Project project) { + String checkstyleToolVersion = DEFAULT_CHECKSTYLE_TOOL_VERSION; + if (project.hasProperty(CHECKSTYLE_TOOL_VERSION_PROPERTY)) { + checkstyleToolVersion = Objects.requireNonNull(project.findProperty(CHECKSTYLE_TOOL_VERSION_PROPERTY)).toString(); + } + return checkstyleToolVersion; + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependencies.java b/buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependencies.java new file mode 100644 index 00000000..586031d1 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependencies.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.gradle.classpath; + +import java.io.IOException; +import java.util.TreeSet; +import java.util.stream.Collectors; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ModuleVersionIdentifier; +import org.gradle.api.artifacts.ResolvedConfiguration; +import org.gradle.api.file.FileCollection; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.TaskAction; + +/** + * A {@link Task} for checking the classpath for prohibited dependencies. + * + * @author Andy Wilkinson + */ +public class CheckClasspathForProhibitedDependencies extends DefaultTask { + + private Configuration classpath; + + public CheckClasspathForProhibitedDependencies() { + getOutputs().upToDateWhen((task) -> true); + } + + public void setClasspath(Configuration classpath) { + this.classpath = classpath; + } + + @Classpath + public FileCollection getClasspath() { + return this.classpath; + } + + @TaskAction + public void checkForProhibitedDependencies() throws IOException { + ResolvedConfiguration resolvedConfiguration = this.classpath.getResolvedConfiguration(); + TreeSet prohibited = resolvedConfiguration.getResolvedArtifacts().stream() + .map((artifact) -> artifact.getModuleVersion().getId()).filter(this::prohibited) + .map((id) -> id.getGroup() + ":" + id.getName()).collect(Collectors.toCollection(TreeSet::new)); + if (!prohibited.isEmpty()) { + StringBuilder message = new StringBuilder(String.format("Found prohibited dependencies in '%s':%n", this.classpath.getName())); + for (String dependency : prohibited) { + message.append(String.format(" %s%n", dependency)); + } + throw new GradleException(message.toString()); + } + } + + private boolean prohibited(ModuleVersionIdentifier id) { + String group = id.getGroup(); + if (group.equals("javax.batch")) { + return false; + } + if (group.equals("javax.cache")) { + return false; + } + if (group.equals("javax.money")) { + return false; + } + // TODO: Uncomment the following lines when upgrading to Spring Framework 6 +// if (group.startsWith("javax")) { +// return true; +// } + if (group.equals("commons-logging")) { + return true; + } + if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) { + return true; + } + if (group.startsWith("org.jboss.spec")) { + return true; + } + if (group.equals("org.apache.geronimo.specs")) { + return true; + } + return false; + } + +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckClasspathForProhibitedDependenciesPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckClasspathForProhibitedDependenciesPlugin.java new file mode 100644 index 00000000..4b92b2e0 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckClasspathForProhibitedDependenciesPlugin.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.gradle.classpath; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.language.base.plugins.LifecycleBasePlugin; + +import org.springframework.util.StringUtils; + +/** + * @author Andy Wilkinson + * @author Rob Winch + */ +public class SpringCheckClasspathForProhibitedDependenciesPlugin implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(SpringCheckProhibitedDependenciesLifecyclePlugin.class); + project.getPlugins().withType(JavaBasePlugin.class, (javaBasePlugin) -> + configureProhibitedDependencyChecks(project)); + } + + private void configureProhibitedDependencyChecks(Project project) { + SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); + sourceSets.all((sourceSet) -> createProhibitedDependenciesChecks(project, + sourceSet.getCompileClasspathConfigurationName(), sourceSet.getRuntimeClasspathConfigurationName())); + } + + private void createProhibitedDependenciesChecks(Project project, String... configurationNames) { + ConfigurationContainer configurations = project.getConfigurations(); + for (String configurationName : configurationNames) { + Configuration configuration = configurations.getByName(configurationName); + createProhibitedDependenciesCheck(configuration, project); + } + } + + private void createProhibitedDependenciesCheck(Configuration classpath, Project project) { + String taskName = "check" + StringUtils.capitalize(classpath.getName() + "ForProhibitedDependencies"); + TaskProvider checkClasspathTask = project.getTasks().register(taskName, + CheckClasspathForProhibitedDependencies.class, (checkClasspath) -> { + checkClasspath.setGroup(LifecycleBasePlugin.CHECK_TASK_NAME); + checkClasspath.setDescription("Checks " + classpath.getName() + " for prohibited dependencies"); + checkClasspath.setClasspath(classpath); + }); + project.getTasks().named(SpringCheckProhibitedDependenciesLifecyclePlugin.CHECK_PROHIBITED_DEPENDENCIES_TASK_NAME, (checkProhibitedTask) -> checkProhibitedTask.dependsOn(checkClasspathTask)); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckProhibitedDependenciesLifecyclePlugin.java b/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckProhibitedDependenciesLifecyclePlugin.java new file mode 100644 index 00000000..a8d649bc --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/classpath/SpringCheckProhibitedDependenciesLifecyclePlugin.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.gradle.classpath; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.tasks.TaskProvider; + +/** + * @author Rob Winch + */ +public class SpringCheckProhibitedDependenciesLifecyclePlugin implements Plugin { + public static final String CHECK_PROHIBITED_DEPENDENCIES_TASK_NAME = "checkForProhibitedDependencies"; + + @Override + public void apply(Project project) { + TaskProvider checkProhibitedDependencies = project.getTasks().register(SpringCheckProhibitedDependenciesLifecyclePlugin.CHECK_PROHIBITED_DEPENDENCIES_TASK_NAME, (task) -> { + task.setGroup(JavaBasePlugin.VERIFICATION_GROUP); + task.setDescription("Checks both the compile/runtime classpath of every SourceSet for prohibited dependencies"); + }); + project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, (checkTask) -> { + checkTask.dependsOn(checkProhibitedDependencies); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocApiPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocApiPlugin.java new file mode 100644 index 00000000..b922bc12 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocApiPlugin.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.docs; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +import io.spring.gradle.convention.SpringModulePlugin; +import org.gradle.api.Action; +import org.gradle.api.JavaVersion; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Rob Winch + * @author Steve Riesenberg + */ +public class SpringJavadocApiPlugin implements Plugin { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Set excludes = Collections.singleton(Pattern.compile("test")); + + @Override + public void apply(Project project) { + // Create task to generate aggregated docs + Javadoc api = project.getTasks().create("api", Javadoc.class, (javadoc) -> { + javadoc.setGroup("Documentation"); + javadoc.setDescription("Generates aggregated Javadoc API documentation."); + }); + + // Note: The following action cannot be a lambda, for groovy compatibility + api.doLast(new Action() { + @Override + public void execute(Task task) { + if (JavaVersion.current().isJava11Compatible()) { + project.copy((copy) -> copy.from(api.getDestinationDir()) + .into(api.getDestinationDir()) + .include("element-list") + .rename("element-list", "package-list")); + } + } + }); + + Set subprojects = project.getRootProject().getSubprojects(); + for (Project subproject : subprojects) { + addProject(api, subproject); + } + + if (subprojects.isEmpty()) { + addProject(api, project); + } + + api.setMaxMemory("1024m"); + api.setDestinationDir(new File(project.getBuildDir(), "api")); + } + + public void setExcludes(String... excludes) { + if (excludes == null) { + this.excludes = Collections.emptySet(); + } + this.excludes = new HashSet<>(excludes.length); + for (String exclude : excludes) { + this.excludes.add(Pattern.compile(exclude)); + } + } + + private void addProject(Javadoc api, Project project) { + for (Pattern exclude : excludes) { + if (exclude.matcher(project.getName()).matches()) { + logger.info("Skipping {} because it is excluded by {}", project, exclude); + return; + } + } + logger.info("Try add sources for {}", project); + project.getPlugins().withType(SpringModulePlugin.class, (plugin) -> { + logger.info("Added sources for {}", project); + + JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class); + SourceSet mainSourceSet = java.getSourceSets().getByName("main"); + + api.setSource(api.getSource().plus(mainSourceSet.getAllJava())); + project.getTasks().withType(Javadoc.class).all((projectJavadoc) -> + api.setClasspath(api.getClasspath().plus(projectJavadoc.getClasspath()))); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocOptionsPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocOptionsPlugin.java new file mode 100644 index 00000000..04d9073d --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/docs/SpringJavadocOptionsPlugin.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.docs; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.gradle.external.javadoc.StandardJavadocDocletOptions; + +/** + * @author Steve Riesenberg + */ +public class SpringJavadocOptionsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getTasks().withType(Javadoc.class, (javadoc) -> { + StandardJavadocDocletOptions options = (StandardJavadocDocletOptions) javadoc.getOptions(); + options.addStringOption("Xdoclint:none", "-quiet"); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/jacoco/SpringJacocoPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/jacoco/SpringJacocoPlugin.java new file mode 100644 index 00000000..010e42bd --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/jacoco/SpringJacocoPlugin.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.jacoco; + +import java.util.Objects; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.testing.jacoco.plugins.JacocoPlugin; +import org.gradle.testing.jacoco.plugins.JacocoPluginExtension; + +/** + * Adds a version of jacoco to use and makes check depend on jacocoTestReport. + * + * @author Rob Winch + * @author Steve Riesenberg + */ +public class SpringJacocoPlugin implements Plugin { + private static final String JACOCO_TOOL_VERSION_PROPERTY = "jacocoToolVersion"; + private static final String DEFAULT_JACOCO_TOOL_VERSION = "0.8.7"; + + @Override + public void apply(Project project) { + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { + project.getPluginManager().apply(JacocoPlugin.class); + project.getTasks().getByName("check").dependsOn(project.getTasks().getByName("jacocoTestReport")); + + JacocoPluginExtension jacoco = project.getExtensions().getByType(JacocoPluginExtension.class); + // NOTE: See gradle.properties#jacocoToolVersion for actual version number + jacoco.setToolVersion(getJacocoToolVersion(project)); + }); + } + + private static String getJacocoToolVersion(Project project) { + String jacocoToolVersion = DEFAULT_JACOCO_TOOL_VERSION; + if (project.hasProperty(JACOCO_TOOL_VERSION_PROPERTY)) { + jacocoToolVersion = Objects.requireNonNull(project.findProperty(JACOCO_TOOL_VERSION_PROPERTY)).toString(); + } + return jacocoToolVersion; + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/management/SpringManagementConfigurationPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/management/SpringManagementConfigurationPlugin.java new file mode 100644 index 00000000..802a2476 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/management/SpringManagementConfigurationPlugin.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2021 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 + * + * https://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.gradle.management; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaTestFixturesPlugin; +import org.gradle.api.plugins.PluginContainer; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.VariantVersionMappingStrategy; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +/** + * Creates a Management configuration that is appropriate for adding a platform to that is not exposed externally. If + * the JavaPlugin is applied, the compileClasspath, runtimeClasspath, testCompileClasspath, and testRuntimeClasspath + * will extend from it. + * @author Rob Winch + * @author Steve Riesenberg + */ +public class SpringManagementConfigurationPlugin implements Plugin { + public static final String MANAGEMENT_CONFIGURATION_NAME = "management"; + + @Override + public void apply(Project project) { + ConfigurationContainer configurations = project.getConfigurations(); + configurations.create(MANAGEMENT_CONFIGURATION_NAME, (management) -> { + management.setVisible(false); + management.setCanBeConsumed(false); + management.setCanBeResolved(false); + + PluginContainer plugins = project.getPlugins(); + plugins.withType(JavaPlugin.class, (javaPlugin) -> { + configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management); + configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management); + configurations.getByName(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management); + configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management); + }); + plugins.withType(JavaTestFixturesPlugin.class, (javaTestFixturesPlugin) -> { + configurations.getByName("testFixturesCompileClasspath").extendsFrom(management); + configurations.getByName("testFixturesRuntimeClasspath").extendsFrom(management); + }); + plugins.withType(MavenPublishPlugin.class, (mavenPublish) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + publishing.getPublications().withType(MavenPublication.class, (mavenPublication) -> + mavenPublication.versionMapping((versions) -> + versions.allVariants(VariantVersionMappingStrategy::fromResolutionResult))); + }); + }); + } +} \ No newline at end of file diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringArtifactoryPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringArtifactoryPlugin.java new file mode 100644 index 00000000..912fafc9 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringArtifactoryPlugin.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin; +import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention; + +import org.springframework.gradle.ProjectUtils; + +/** + * @author Steve Riesenberg + */ +public class SpringArtifactoryPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply base plugin + project.getPlugins().apply(ArtifactoryPlugin.class); + + // Apply artifactory repository configuration + boolean isSnapshot = ProjectUtils.isSnapshot(project); + boolean isMilestone = ProjectUtils.isMilestone(project); + + @SuppressWarnings("deprecation") + ArtifactoryPluginConvention artifactoryExtension = project.getConvention().getPlugin(ArtifactoryPluginConvention.class); + artifactoryExtension.artifactory((artifactory) -> { + artifactory.setContextUrl("https://repo.spring.io"); + artifactory.publish((publish) -> { + publish.repository((repository) -> { + String repoKey = isSnapshot ? "libs-snapshot-local" : isMilestone ? "libs-milestone-local" : "libs-release-local"; + repository.setRepoKey(repoKey); + if (project.hasProperty("artifactoryUsername")) { + repository.setUsername(project.findProperty("artifactoryUsername")); + repository.setPassword(project.findProperty("artifactoryPassword")); + } + }); + publish.defaults((defaults) -> defaults.publications("mavenJava")); + }); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringMavenPublishingConventionsPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringMavenPublishingConventionsPlugin.java new file mode 100644 index 00000000..ef7152b1 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringMavenPublishingConventionsPlugin.java @@ -0,0 +1,106 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import java.util.Collections; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPom; +import org.gradle.api.publish.maven.MavenPomDeveloperSpec; +import org.gradle.api.publish.maven.MavenPomIssueManagement; +import org.gradle.api.publish.maven.MavenPomLicenseSpec; +import org.gradle.api.publish.maven.MavenPomOrganization; +import org.gradle.api.publish.maven.MavenPomScm; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringMavenPublishingConventionsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().withType(MavenPublishPlugin.class, (mavenPublish) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + publishing.getPublications().withType(MavenPublication.class, (mavenPublication) -> + customizePom(mavenPublication.getPom(), project)); + SpringMavenPublishingConventionsPlugin.this.customizeJavaPlugin(project); + }); + } + + private void customizePom(MavenPom pom, Project project) { + pom.getUrl().set("https://spring.io/projects/spring-authorization-server"); + pom.getName().set(project.provider(project::getName)); + pom.getDescription().set(project.provider(project::getDescription)); + pom.organization(this::customizeOrganization); + pom.licenses(this::customizeLicences); + pom.developers(this::customizeDevelopers); + pom.scm(this::customizeScm); + pom.issueManagement(this::customizeIssueManagement); + } + + private void customizeOrganization(MavenPomOrganization organization) { + organization.getName().set("VMware, Inc."); + organization.getUrl().set("https://spring.io"); + } + + private void customizeLicences(MavenPomLicenseSpec licences) { + licences.license((licence) -> { + licence.getName().set("Apache License, Version 2.0"); + licence.getUrl().set("https://www.apache.org/licenses/LICENSE-2.0"); + }); + } + + private void customizeDevelopers(MavenPomDeveloperSpec developers) { + developers.developer((developer) -> { + developer.getName().set("Joe Grandja"); + developer.getEmail().set("jgrandja@vmware.com"); + developer.getOrganization().set("VMware, Inc."); + developer.getOrganizationUrl().set("https://spring.io"); + developer.getRoles().set(Collections.singletonList("Project lead")); + }); + developers.developer((developer) -> { + developer.getName().set("Steve Riesenberg"); + developer.getEmail().set("sriesenberg@vmware.com"); + developer.getOrganization().set("VMware, Inc."); + developer.getOrganizationUrl().set("https://spring.io"); + }); + } + + private void customizeScm(MavenPomScm scm) { + scm.getConnection().set("scm:git:git://github.com/spring-projects/spring-authorization-server.git"); + scm.getDeveloperConnection().set("scm:git:ssh://git@github.com/spring-projects/spring-authorization-server.git"); + scm.getUrl().set("https://github.com/spring-projects/spring-authorization-server"); + } + + private void customizeIssueManagement(MavenPomIssueManagement issueManagement) { + issueManagement.getSystem().set("GitHub"); + issueManagement.getUrl().set("https://github.com/spring-projects/spring-authorization-server/issues"); + } + + private void customizeJavaPlugin(Project project) { + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { + JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class); + extension.withJavadocJar(); + extension.withSourcesJar(); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringNexusPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringNexusPlugin.java new file mode 100644 index 00000000..6a486e47 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringNexusPlugin.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import java.net.URI; +import java.time.Duration; + +import io.github.gradlenexus.publishplugin.NexusPublishExtension; +import io.github.gradlenexus.publishplugin.NexusPublishPlugin; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; + +import org.springframework.gradle.ProjectUtils; + +/** + * @author Steve Riesenberg + */ +public class SpringNexusPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply nexus publish plugin + project.getPlugins().apply(NexusPublishPlugin.class); + + // Create ossrh repository + NexusPublishExtension nexusPublishing = project.getExtensions().getByType(NexusPublishExtension.class); + nexusPublishing.getRepositories().create("ossrh", (nexusRepository) -> { + nexusRepository.getNexusUrl().set(URI.create("https://s01.oss.sonatype.org/service/local/")); + nexusRepository.getSnapshotRepositoryUrl().set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/")); + }); + + // Configure timeouts + nexusPublishing.getConnectTimeout().set(Duration.ofMinutes(3)); + nexusPublishing.getClientTimeout().set(Duration.ofMinutes(3)); + + // Ensure release build automatically closes and releases staging repository + Task finalizeDeployArtifacts = project.task("finalizeDeployArtifacts"); + if (ProjectUtils.isRelease(project) && project.hasProperty("ossrhUsername")) { + Task closeAndReleaseOssrhStagingRepository = project.getTasks().findByName("closeAndReleaseOssrhStagingRepository"); + finalizeDeployArtifacts.dependsOn(closeAndReleaseOssrhStagingRepository); + } + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishAllJavaComponentsPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishAllJavaComponentsPlugin.java new file mode 100644 index 00000000..58999b6a --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishAllJavaComponentsPlugin.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlatformPlugin; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringPublishAllJavaComponentsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().withType(MavenPublishPlugin.class, (mavenPublish) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + publishing.getPublications().create("mavenJava", MavenPublication.class, (maven) -> { + project.getPlugins().withType(JavaPlugin.class, (plugin) -> + maven.from(project.getComponents().getByName("java"))); + project.getPlugins().withType(JavaPlatformPlugin.class, (plugin) -> + maven.from(project.getComponents().getByName("javaPlatform"))); + }); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishArtifactsPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishArtifactsPlugin.java new file mode 100644 index 00000000..8868bc5d --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishArtifactsPlugin.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +import org.springframework.gradle.ProjectUtils; + +/** + * @author Steve Riesenberg + */ +public class SpringPublishArtifactsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getTasks().register("publishArtifacts", (publishArtifacts) -> { + publishArtifacts.setGroup("Publishing"); + publishArtifacts.setDescription("Publish the artifacts to either Artifactory or Maven Central based on the version"); + if (ProjectUtils.isRelease(project)) { + publishArtifacts.dependsOn("publishToOssrh"); + } else { + publishArtifacts.dependsOn("artifactoryPublish"); + } + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishLocalPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishLocalPlugin.java new file mode 100644 index 00000000..d52cbbae --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringPublishLocalPlugin.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import java.io.File; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringPublishLocalPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().withType(MavenPublishPlugin.class, (mavenPublish) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + publishing.getRepositories().maven((maven) -> { + maven.setName("local"); + maven.setUrl(new File(project.getRootProject().getBuildDir(), "publications/repos")); + }); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringRepositoryPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringRepositoryPlugin.java new file mode 100644 index 00000000..63895b65 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringRepositoryPlugin.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +import org.springframework.gradle.ProjectUtils; + +/** + * @author Steve Riesenberg + */ +public class SpringRepositoryPlugin implements Plugin { + @Override + public void apply(Project project) { + List forceMavenRepositories = Collections.emptyList(); + if (project.hasProperty("forceMavenRepositories")) { + forceMavenRepositories = Arrays.asList(((String) project.findProperty("forceMavenRepositories")).split(",")); + } + + boolean isImplicitSnapshotRepository = forceMavenRepositories.isEmpty() && ProjectUtils.isSnapshot(project); + boolean isImplicitMilestoneRepository = forceMavenRepositories.isEmpty() && ProjectUtils.isMilestone(project); + + boolean isSnapshot = isImplicitSnapshotRepository || forceMavenRepositories.contains("snapshot"); + boolean isMilestone = isImplicitMilestoneRepository || forceMavenRepositories.contains("milestone"); + + if (forceMavenRepositories.contains("local")) { + project.getRepositories().mavenLocal(); + } + project.getRepositories().mavenCentral(); + if (isSnapshot) { + repository(project, "artifactory-snapshot", "https://repo.spring.io/snapshot/"); + } + if (isSnapshot || isMilestone) { + repository(project, "artifactory-milestone", "https://repo.spring.io/milestone/"); + } + repository(project, "artifactory-release", "https://repo.spring.io/release/"); + } + + private void repository(Project project, String name, String url) { + project.getRepositories().maven((repo) -> { + repo.setName(name); + if (project.hasProperty("artifactoryUsername")) { + repo.credentials((credentials) -> { + credentials.setUsername(Objects.requireNonNull(project.findProperty("artifactoryUsername")).toString()); + credentials.setPassword(Objects.requireNonNull(project.findProperty("artifactoryPassword")).toString()); + }); + } + repo.setUrl(url); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/maven/SpringSigningPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringSigningPlugin.java new file mode 100644 index 00000000..5d5e8704 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/maven/SpringSigningPlugin.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.maven; + +import java.util.concurrent.Callable; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.publish.Publication; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.plugins.signing.SigningExtension; +import org.gradle.plugins.signing.SigningPlugin; + +/** + * @author Steve Riesenberg + */ +public class SpringSigningPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getPluginManager().apply(SigningPlugin.class); + project.getPlugins().withType(SigningPlugin.class, (signingPlugin) -> { + boolean hasSigningKey = project.hasProperty("signing.keyId") || project.hasProperty("signingKey"); + if (hasSigningKey) { + sign(project); + } + }); + } + + private void sign(Project project) { + SigningExtension signing = project.getExtensions().getByType(SigningExtension.class); + signing.setRequired((Callable) () -> project.getGradle().getTaskGraph().hasTask("publishArtifacts")); + + String signingKeyId = (String) project.findProperty("signingKeyId"); + String signingKey = (String) project.findProperty("signingKey"); + String signingPassword = (String) project.findProperty("signingPassword"); + if (signingKeyId != null) { + signing.useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword); + } else { + signing.useInMemoryPgpKeys(signingKey, signingPassword); + } + project.getPlugins().withType(SpringPublishAllJavaComponentsPlugin.class, (publishingPlugin) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + Publication maven = publishing.getPublications().getByName("mavenJava"); + signing.sign(maven); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/nohttp/SpringNoHttpPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/nohttp/SpringNoHttpPlugin.java new file mode 100644 index 00000000..364b4f20 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/nohttp/SpringNoHttpPlugin.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.nohttp; + +import java.io.File; + +import io.spring.nohttp.gradle.NoHttpExtension; +import io.spring.nohttp.gradle.NoHttpPlugin; +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +/** + * @author Steve Riesenberg + */ +public class SpringNoHttpPlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply nohttp plugin + project.getPluginManager().apply(NoHttpPlugin.class); + + // Configure nohttp + NoHttpExtension nohttp = project.getExtensions().getByType(NoHttpExtension.class); + File allowlistFile = project.getRootProject().file("etc/nohttp/allowlist.lines"); + nohttp.setAllowlistFile(allowlistFile); + nohttp.getSource().exclude("buildSrc/build/**"); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsEclipsePlugin.java b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsEclipsePlugin.java new file mode 100644 index 00000000..75a745b2 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsEclipsePlugin.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.propdeps; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.PluginManager; +import org.gradle.plugins.ide.eclipse.EclipsePlugin; +import org.gradle.plugins.ide.eclipse.EclipseWtpPlugin; +import org.gradle.plugins.ide.eclipse.model.EclipseModel; + +/** + * Plugin to allow optional and provided dependency configurations to work with the + * standard gradle 'eclipse' plugin + * + * @author Phillip Webb + * @author Steve Riesenberg + */ +public class SpringPropDepsEclipsePlugin implements Plugin { + @Override + public void apply(Project project) { + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(SpringPropDepsPlugin.class); + pluginManager.apply(EclipsePlugin.class); + pluginManager.apply(EclipseWtpPlugin.class); + + EclipseModel eclipseModel = project.getExtensions().getByType(EclipseModel.class); + eclipseModel.classpath((classpath) -> { + classpath.getPlusConfigurations().add(project.getConfigurations().getByName("provided")); + classpath.getPlusConfigurations().add(project.getConfigurations().getByName("optional")); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsIdeaPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsIdeaPlugin.java new file mode 100644 index 00000000..47e0a3a7 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsIdeaPlugin.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.propdeps; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.PluginManager; +import org.gradle.plugins.ide.idea.IdeaPlugin; +import org.gradle.plugins.ide.idea.model.IdeaModel; + +/** + * Plugin to allow optional and provided dependency configurations to work with the + * standard gradle 'idea' plugin + * + * @author Phillip Webb + * @author Brian Clozel + * @author Steve Riesenberg + * @link https://youtrack.jetbrains.com/issue/IDEA-107046 + * @link https://youtrack.jetbrains.com/issue/IDEA-117668 + */ +public class SpringPropDepsIdeaPlugin implements Plugin { + @Override + public void apply(Project project) { + PluginManager pluginManager = project.getPluginManager(); + pluginManager.apply(SpringPropDepsPlugin.class); + pluginManager.apply(IdeaPlugin.class); + + IdeaModel ideaModel = project.getExtensions().getByType(IdeaModel.class); + ideaModel.module((idea) -> { + // IDEA internally deals with 4 scopes : COMPILE, TEST, PROVIDED, RUNTIME + // but only PROVIDED seems to be picked up + idea.getScopes().get("PROVIDED").get("plus").add(project.getConfigurations().getByName("provided")); + idea.getScopes().get("PROVIDED").get("plus").add(project.getConfigurations().getByName("optional")); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsPlugin.java new file mode 100644 index 00000000..2a0a5919 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/propdeps/SpringPropDepsPlugin.java @@ -0,0 +1,80 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.propdeps; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.plugins.JavaLibraryPlugin; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.tasks.javadoc.Javadoc; + +import org.springframework.gradle.management.SpringManagementConfigurationPlugin; + +/** + * Plugin to allow 'optional' and 'provided' dependency configurations + * + * As stated in the maven documentation, provided scope "is only available on the compilation and test classpath, + * and is not transitive". + * + * This plugin creates two new configurations, and each one: + *
    + *
  • is a parent of the compile configuration
  • + *
  • is not visible, not transitive
  • + *
  • all dependencies are excluded from the default configuration
  • + *
+ * + * @author Phillip Webb + * @author Brian Clozel + * @author Rob Winch + * @author Steve Riesenberg + * + * @see Maven documentation + * @see Gradle configurations + * @see SpringPropDepsEclipsePlugin + * @see SpringPropDepsIdeaPlugin + */ +public class SpringPropDepsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { + Configuration provided = addConfiguration(project, "provided"); + Configuration optional = addConfiguration(project, "optional"); + + Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); + javadoc.setClasspath(javadoc.getClasspath().plus(provided).plus(optional)); + }); + } + + private Configuration addConfiguration(Project project, String name) { + Configuration configuration = project.getConfigurations().create(name); + configuration.extendsFrom(project.getConfigurations().getByName("implementation")); + project.getPlugins().withType(JavaLibraryPlugin.class, (javaLibraryPlugin) -> + configuration.extendsFrom(project.getConfigurations().getByName("api"))); + project.getPlugins().withType(SpringManagementConfigurationPlugin.class, (springManagementConfigurationPlugin) -> + configuration.extendsFrom(project.getConfigurations().getByName("management"))); + + JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class); + java.getSourceSets().all((sourceSet) -> { + sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(configuration)); + sourceSet.setRuntimeClasspath(sourceSet.getRuntimeClasspath().plus(configuration)); + }); + + return configuration; + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/properties/SpringCopyPropertiesPlugin.java b/buildSrc/src/main/java/org/springframework/gradle/properties/SpringCopyPropertiesPlugin.java new file mode 100644 index 00000000..bb7bf39d --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/properties/SpringCopyPropertiesPlugin.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.properties; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +/** + * @author Steve Riesenberg + */ +public class SpringCopyPropertiesPlugin implements Plugin { + @Override + public void apply(Project project) { + copyPropertyFromRootProjectTo("group", project); + copyPropertyFromRootProjectTo("version", project); + copyPropertyFromRootProjectTo("description", project); + } + + private void copyPropertyFromRootProjectTo(String propertyName, Project project) { + Project rootProject = project.getRootProject(); + Object property = rootProject.findProperty(propertyName); + if (property != null) { + project.setProperty(propertyName, property); + } + } +} diff --git a/buildSrc/src/main/java/org/springframework/gradle/sonarqube/SpringSonarQubePlugin.java b/buildSrc/src/main/java/org/springframework/gradle/sonarqube/SpringSonarQubePlugin.java new file mode 100644 index 00000000..f05a5a3a --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/gradle/sonarqube/SpringSonarQubePlugin.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.gradle.sonarqube; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.sonarqube.gradle.SonarQubeExtension; +import org.sonarqube.gradle.SonarQubePlugin; + +import org.springframework.gradle.ProjectUtils; + +/** + * @author Steve Riesenberg + */ +public class SpringSonarQubePlugin implements Plugin { + @Override + public void apply(Project project) { + // Apply sonarqube plugin + project.getPluginManager().apply(SonarQubePlugin.class); + + // Configure sonarqube + SonarQubeExtension sonarqube = project.getExtensions().getByType(SonarQubeExtension.class); + sonarqube.properties((properties) -> { + String projectName = ProjectUtils.getProjectName(project); + properties.property("sonar.java.coveragePlugin", "jacoco"); + properties.property("sonar.projectName", projectName); + properties.property("sonar.jacoco.reportPath", project.getBuildDir().getName() + "/jacoco.exec"); + properties.property("sonar.links.homepage", "https://spring.io/" + projectName); + properties.property("sonar.links.ci", "https://jenkins.spring.io/job/" + projectName + "/"); + properties.property("sonar.links.issue", "https://github.com/spring-projects/" + projectName + "/issues"); + properties.property("sonar.links.scm", "https://github.com/spring-projects/" + projectName); + properties.property("sonar.links.scm_dev", "https://github.com/spring-projects/" + projectName + ".git"); + }); + } +} diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.docs.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.docs.properties new file mode 100644 index 00000000..a2643dd4 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.docs.properties @@ -0,0 +1 @@ +implementation-class=io.spring.gradle.convention.SpringDocsPlugin \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.root.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.root.properties new file mode 100644 index 00000000..4db8b53b --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.root.properties @@ -0,0 +1 @@ +implementation-class=io.spring.gradle.convention.SpringRootProjectPlugin \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.spring-module.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.spring-module.properties new file mode 100644 index 00000000..124dd85f --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/io.spring.convention.spring-module.properties @@ -0,0 +1 @@ +implementation-class=io.spring.gradle.convention.SpringModulePlugin \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/org.springframework.gradle.deploy-docs.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.springframework.gradle.deploy-docs.properties new file mode 100644 index 00000000..e135a0a7 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.springframework.gradle.deploy-docs.properties @@ -0,0 +1,2 @@ +# Referencing this plugin by ID allows java code to depend on groovy compilation +implementation-class=org.springframework.gradle.docs.SpringDeployDocsPlugin \ No newline at end of file