Bladeren bron

Add CheckClasspathForProhibitedDependencies

Issues gh-10499 gh-10501
Rob Winch 3 jaren geleden
bovenliggende
commit
d146bcb7fc

+ 5 - 0
build.gradle

@@ -166,3 +166,8 @@ tasks.register('checkSamples') {
 s101 {
 	configurationDirectory = project.file("etc/s101")
 }
+
+tasks.register('checkForProhibitedDependencies', check -> {
+	check.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP)
+	check.setDescription("Checks for prohibited dependencies")
+})

+ 2 - 0
buildSrc/src/main/groovy/io/spring/gradle/convention/SpringModulePlugin.groovy

@@ -20,6 +20,7 @@ import org.gradle.api.Project
 import org.gradle.api.plugins.JavaLibraryPlugin;
 import org.gradle.api.plugins.MavenPlugin;
 import org.gradle.api.plugins.PluginManager
+import org.springframework.gradle.classpath.CheckClasspathForProhibitedDependenciesPlugin;
 import org.springframework.gradle.maven.SpringMavenPlugin;
 
 /**
@@ -32,6 +33,7 @@ class SpringModulePlugin extends AbstractSpringJavaPlugin {
 		PluginManager pluginManager = project.getPluginManager();
 		pluginManager.apply(JavaLibraryPlugin.class)
 		pluginManager.apply(SpringMavenPlugin.class);
+		pluginManager.apply(CheckClasspathForProhibitedDependenciesPlugin.class);
 		pluginManager.apply("io.spring.convention.jacoco");
 
 		def deployArtifacts = project.task("deployArtifacts")

+ 99 - 0
buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependencies.java

@@ -0,0 +1,99 @@
+/*
+ * 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.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;
+
+import java.io.IOException;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+/**
+ * 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<String> 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;
+		}
+		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;
+	}
+
+}

+ 75 - 0
buildSrc/src/main/java/org/springframework/gradle/classpath/CheckClasspathForProhibitedDependenciesPlugin.java

@@ -0,0 +1,75 @@
+/*
+ * 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.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 CheckClasspathForProhibitedDependenciesPlugin implements Plugin<Project> {
+	public static final String CHECK_PROHIBITED_DEPENDENCIES_TASK_NAME = "checkForProhibitedDependencies";
+
+	@Override
+	public void apply(Project project) {
+		project.getPlugins().withType(JavaBasePlugin.class, javaBasePlugin -> {
+			configureProhibitedDependencyChecks(project);
+		});
+	}
+
+	private void configureProhibitedDependencyChecks(Project project) {
+		TaskProvider<Task> checkProhibitedDependencies = project.getTasks().register(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);
+		});
+		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<CheckClasspathForProhibitedDependencies> 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(CHECK_PROHIBITED_DEPENDENCIES_TASK_NAME, checkProhibitedTask -> checkProhibitedTask.dependsOn(checkClasspathTask));
+	}
+}