|
|
@ -38,6 +38,7 @@ import org.gradle.api.artifacts.ExcludeRule;
|
|
|
|
import org.gradle.api.artifacts.ModuleDependency;
|
|
|
|
import org.gradle.api.artifacts.ModuleDependency;
|
|
|
|
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
|
|
|
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
|
|
|
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
|
|
|
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
|
|
|
|
|
|
|
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
|
|
|
|
import org.gradle.api.tasks.Input;
|
|
|
|
import org.gradle.api.tasks.Input;
|
|
|
|
import org.gradle.api.tasks.TaskAction;
|
|
|
|
import org.gradle.api.tasks.TaskAction;
|
|
|
|
|
|
|
|
|
|
|
@ -48,6 +49,9 @@ import org.gradle.api.tasks.TaskAction;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
|
|
|
|
public class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Map<String, String> SPRING_BOOT_DEPENDENCIES_PROJECT = Collections.singletonMap("path",
|
|
|
|
|
|
|
|
":spring-boot-project:spring-boot-dependencies");
|
|
|
|
|
|
|
|
|
|
|
|
private final Map<String, Set<String>> exclusionsByDependencyId = new TreeMap<>();
|
|
|
|
private final Map<String, Set<String>> exclusionsByDependencyId = new TreeMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
private final Map<String, Dependency> dependencyById = new HashMap<>();
|
|
|
|
private final Map<String, Dependency> dependencyById = new HashMap<>();
|
|
|
@ -63,28 +67,32 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
|
|
|
|
ConfigurationContainer configurations) {
|
|
|
|
ConfigurationContainer configurations) {
|
|
|
|
this.dependencyHandler = getProject().getDependencies();
|
|
|
|
this.dependencyHandler = getProject().getDependencies();
|
|
|
|
this.configurations = getProject().getConfigurations();
|
|
|
|
this.configurations = getProject().getConfigurations();
|
|
|
|
this.platform = this.dependencyHandler.create(this.dependencyHandler.platform(this.dependencyHandler
|
|
|
|
this.platform = this.dependencyHandler.create(
|
|
|
|
.project(Collections.singletonMap("path", ":spring-boot-project:spring-boot-dependencies"))));
|
|
|
|
this.dependencyHandler.platform(this.dependencyHandler.project(SPRING_BOOT_DEPENDENCIES_PROJECT)));
|
|
|
|
getOutputs().upToDateWhen((task) -> true);
|
|
|
|
getOutputs().upToDateWhen((task) -> true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setClasspath(Configuration classpath) {
|
|
|
|
public void setClasspath(Configuration classpath) {
|
|
|
|
this.exclusionsByDependencyId.clear();
|
|
|
|
this.exclusionsByDependencyId.clear();
|
|
|
|
this.dependencyById.clear();
|
|
|
|
this.dependencyById.clear();
|
|
|
|
classpath.getAllDependencies().all((dependency) -> {
|
|
|
|
classpath.getAllDependencies().all(this::processDependency);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void processDependency(Dependency dependency) {
|
|
|
|
if (dependency instanceof ModuleDependency) {
|
|
|
|
if (dependency instanceof ModuleDependency) {
|
|
|
|
String dependencyId = dependency.getGroup() + ":" + dependency.getName();
|
|
|
|
processDependency((ModuleDependency) dependency);
|
|
|
|
Set<ExcludeRule> excludeRules = ((ModuleDependency) dependency).getExcludeRules();
|
|
|
|
}
|
|
|
|
TreeSet<String> exclusions = excludeRules.stream()
|
|
|
|
}
|
|
|
|
.map((rule) -> rule.getGroup() + ":" + rule.getModule())
|
|
|
|
|
|
|
|
|
|
|
|
private void processDependency(ModuleDependency dependency) {
|
|
|
|
|
|
|
|
String dependencyId = getId(dependency);
|
|
|
|
|
|
|
|
TreeSet<String> exclusions = dependency.getExcludeRules().stream().map(this::getId)
|
|
|
|
.collect(Collectors.toCollection(TreeSet::new));
|
|
|
|
.collect(Collectors.toCollection(TreeSet::new));
|
|
|
|
this.exclusionsByDependencyId.put(dependencyId, exclusions);
|
|
|
|
this.exclusionsByDependencyId.put(dependencyId, exclusions);
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
this.dependencyById.put(dependencyId, getProject().getDependencies().create(dependencyId));
|
|
|
|
this.dependencyById.put(dependencyId, getProject().getDependencies().create(dependencyId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Input
|
|
|
|
@Input
|
|
|
|
Map<String, Set<String>> getExclusionsByDependencyId() {
|
|
|
|
Map<String, Set<String>> getExclusionsByDependencyId() {
|
|
|
@ -94,24 +102,24 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
|
|
|
|
@TaskAction
|
|
|
|
@TaskAction
|
|
|
|
public void checkForUnnecessaryExclusions() {
|
|
|
|
public void checkForUnnecessaryExclusions() {
|
|
|
|
Map<String, Set<String>> unnecessaryExclusions = new HashMap<>();
|
|
|
|
Map<String, Set<String>> unnecessaryExclusions = new HashMap<>();
|
|
|
|
for (Entry<String, Set<String>> entry : this.exclusionsByDependencyId.entrySet()) {
|
|
|
|
this.exclusionsByDependencyId.forEach((dependencyId, exclusions) -> {
|
|
|
|
String dependencyId = entry.getKey();
|
|
|
|
|
|
|
|
Set<String> exclusions = entry.getValue();
|
|
|
|
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
Dependency toCheck = this.dependencyById.get(dependencyId);
|
|
|
|
Dependency toCheck = this.dependencyById.get(dependencyId);
|
|
|
|
List<String> dependencies = this.configurations.detachedConfiguration(toCheck, this.platform)
|
|
|
|
List<String> dependencies = this.configurations.detachedConfiguration(toCheck, this.platform)
|
|
|
|
.getIncoming().getArtifacts().getArtifacts().stream().map((artifact) -> {
|
|
|
|
.getIncoming().getArtifacts().getArtifacts().stream().map(this::getId)
|
|
|
|
ModuleComponentIdentifier id = (ModuleComponentIdentifier) artifact.getId()
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
.getComponentIdentifier();
|
|
|
|
|
|
|
|
return id.getGroup() + ":" + id.getModule();
|
|
|
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
|
|
|
exclusions.removeAll(dependencies);
|
|
|
|
exclusions.removeAll(dependencies);
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
if (!exclusions.isEmpty()) {
|
|
|
|
unnecessaryExclusions.put(dependencyId, exclusions);
|
|
|
|
unnecessaryExclusions.put(dependencyId, exclusions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!unnecessaryExclusions.isEmpty()) {
|
|
|
|
if (!unnecessaryExclusions.isEmpty()) {
|
|
|
|
|
|
|
|
throw new GradleException(getExceptionMessage(unnecessaryExclusions));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getExceptionMessage(Map<String, Set<String>> unnecessaryExclusions) {
|
|
|
|
StringBuilder message = new StringBuilder("Unnecessary exclusions detected:");
|
|
|
|
StringBuilder message = new StringBuilder("Unnecessary exclusions detected:");
|
|
|
|
for (Entry<String, Set<String>> entry : unnecessaryExclusions.entrySet()) {
|
|
|
|
for (Entry<String, Set<String>> entry : unnecessaryExclusions.entrySet()) {
|
|
|
|
message.append(String.format("%n %s", entry.getKey()));
|
|
|
|
message.append(String.format("%n %s", entry.getKey()));
|
|
|
@ -119,8 +127,23 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
|
|
|
|
message.append(String.format("%n %s", exclusion));
|
|
|
|
message.append(String.format("%n %s", exclusion));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new GradleException(message.toString());
|
|
|
|
return message.toString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getId(ResolvedArtifactResult artifact) {
|
|
|
|
|
|
|
|
return getId((ModuleComponentIdentifier) artifact.getId().getComponentIdentifier());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getId(ModuleDependency dependency) {
|
|
|
|
|
|
|
|
return dependency.getGroup() + ":" + dependency.getName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getId(ExcludeRule rule) {
|
|
|
|
|
|
|
|
return rule.getGroup() + ":" + rule.getModule();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getId(ModuleComponentIdentifier identifier) {
|
|
|
|
|
|
|
|
return identifier.getGroup() + ":" + identifier.getModule();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|