Skip to content

Commit addc1f7

Browse files
author
Phillip Webb
committed
Support transitive excludes in dependency-tools
Update spring-boot-dependency-tools to support transitive excludes. Transitive excludes are useful with Gradle which considers each dependency independently (see GRADLE-3061). Transitive excludes are supported by parsing the dependency-tree file from spring-boot-versions. See gh-1047
1 parent 28090e8 commit addc1f7

File tree

12 files changed

+1604
-4
lines changed

12 files changed

+1604
-4
lines changed

spring-boot-tools/spring-boot-dependency-tools/pom.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<artifactId>maven-dependency-plugin</artifactId>
3232
<executions>
3333
<execution>
34-
<id>copy-effective-pom</id>
34+
<id>copy-resources</id>
3535
<phase>generate-resources</phase>
3636
<goals>
3737
<goal>copy</goal>
@@ -47,6 +47,15 @@
4747
<outputDirectory>${generated.pom.dir}</outputDirectory>
4848
<destFileName>effective-pom.xml</destFileName>
4949
</artifactItem>
50+
<artifactItem>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-versions</artifactId>
53+
<version>${project.version}</version>
54+
<type>dependency-tree</type>
55+
<overWrite>true</overWrite>
56+
<outputDirectory>${generated.pom.dir}</outputDirectory>
57+
<destFileName>dependency-tree.txt</destFileName>
58+
</artifactItem>
5059
</artifactItems>
5160
</configuration>
5261
</execution>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.dependency.tools;
18+
19+
import java.util.ArrayList;
20+
import java.util.LinkedHashMap;
21+
import java.util.LinkedHashSet;
22+
import java.util.Map;
23+
import java.util.Set;
24+
25+
import org.springframework.boot.dependency.tools.Dependency.Exclusion;
26+
import org.springframework.boot.dependency.tools.Dependency.ExclusionType;
27+
28+
/**
29+
* {@link Dependencies} to extend an existing {@link Dependencies} instance with
30+
* transitive {@link Exclusion}s located from a {@link DependencyTree}.
31+
*
32+
* @author Phillip Webb
33+
* @since 1.1.0
34+
*/
35+
class DependenciesWithTransitiveExclusions extends AbstractDependencies {
36+
37+
public DependenciesWithTransitiveExclusions(Dependencies dependencies,
38+
DependencyTree tree) {
39+
DependencyBuilder builder = new DependencyBuilder(dependencies);
40+
builder.addTransitiveExcludes(tree);
41+
builder.finish();
42+
}
43+
44+
/**
45+
* Builder used to collect the transitive exclusions.
46+
*/
47+
private class DependencyBuilder {
48+
49+
private Map<ArtifactAndGroupId, DependencyAndTransitiveExclusions> dependencies;
50+
51+
public DependencyBuilder(Dependencies dependencies) {
52+
this.dependencies = new LinkedHashMap<ArtifactAndGroupId, DependencyAndTransitiveExclusions>();
53+
for (Dependency dependency : dependencies) {
54+
this.dependencies.put(new ArtifactAndGroupId(dependency),
55+
new DependencyAndTransitiveExclusions(dependency));
56+
}
57+
}
58+
59+
public void addTransitiveExcludes(DependencyTree tree) {
60+
for (DependencyNode node : tree) {
61+
DependencyAndTransitiveExclusions dependency = this.dependencies
62+
.get(asArtifactAndGroupId(node));
63+
if (dependency != null) {
64+
for (DependencyNode child : node) {
65+
addTransitiveExcludes(dependency, child);
66+
}
67+
}
68+
}
69+
}
70+
71+
private void addTransitiveExcludes(DependencyAndTransitiveExclusions dependency,
72+
DependencyNode node) {
73+
DependencyAndTransitiveExclusions exclusions = this.dependencies
74+
.get(asArtifactAndGroupId(node));
75+
if (exclusions != null) {
76+
dependency.addTransitiveExclusions(exclusions.getSourceDependency());
77+
}
78+
for (DependencyNode child : node) {
79+
addTransitiveExcludes(dependency, child);
80+
}
81+
}
82+
83+
private ArtifactAndGroupId asArtifactAndGroupId(DependencyNode node) {
84+
return new ArtifactAndGroupId(node.getGroupId(), node.getArtifactId());
85+
}
86+
87+
public void finish() {
88+
for (Map.Entry<ArtifactAndGroupId, DependencyAndTransitiveExclusions> entry : this.dependencies
89+
.entrySet()) {
90+
add(entry.getKey(), entry.getValue().createNewDependency());
91+
}
92+
}
93+
94+
}
95+
96+
/**
97+
* Holds a {@link Dependency} with additional transitive {@link Exclusion}s.
98+
*/
99+
private static class DependencyAndTransitiveExclusions {
100+
101+
private Dependency dependency;
102+
103+
private Set<Exclusion> transitiveExclusions = new LinkedHashSet<Exclusion>();
104+
105+
public DependencyAndTransitiveExclusions(Dependency dependency) {
106+
this.dependency = dependency;
107+
}
108+
109+
public Dependency getSourceDependency() {
110+
return this.dependency;
111+
}
112+
113+
public void addTransitiveExclusions(Dependency dependency) {
114+
for (Exclusion exclusion : dependency.getExclusions()) {
115+
this.transitiveExclusions.add(new Exclusion(exclusion.getGroupId(),
116+
exclusion.getArtifactId(), ExclusionType.TRANSITIVE));
117+
}
118+
}
119+
120+
public Dependency createNewDependency() {
121+
Set<Exclusion> exclusions = new LinkedHashSet<Dependency.Exclusion>();
122+
exclusions.addAll(this.dependency.getExclusions());
123+
exclusions.addAll(this.transitiveExclusions);
124+
return new Dependency(this.dependency.getGroupId(),
125+
this.dependency.getArtifactId(), this.dependency.getVersion(),
126+
new ArrayList<Exclusion>(exclusions));
127+
}
128+
129+
}
130+
131+
}

spring-boot-tools/spring-boot-dependency-tools/src/main/java/org/springframework/boot/dependency/tools/Dependency.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,15 @@ public static final class Exclusion {
137137

138138
private final String artifactId;
139139

140-
Exclusion(String groupId, String artifactId) {
140+
private final ExclusionType type;
141+
142+
Exclusion(String groupId, String artifactId, ExclusionType type) {
141143
Assert.notNull(groupId, "GroupId must not be null");
142144
Assert.notNull(groupId, "ArtifactId must not be null");
145+
Assert.notNull(type, "Type must not be null");
143146
this.groupId = groupId;
144147
this.artifactId = artifactId;
148+
this.type = type;
145149
}
146150

147151
/**
@@ -158,6 +162,10 @@ public String getGroupId() {
158162
return this.groupId;
159163
}
160164

165+
public ExclusionType getType() {
166+
return this.type;
167+
}
168+
161169
@Override
162170
public String toString() {
163171
return this.groupId + ":" + this.artifactId;
@@ -188,4 +196,22 @@ public boolean equals(Object obj) {
188196

189197
}
190198

199+
public static enum ExclusionType {
200+
201+
/**
202+
* An exclusion that was specified directly on the dependency.
203+
*/
204+
DIRECT,
205+
206+
/**
207+
* An exclusion that is was specified on a dependency of this dependency. For
208+
* example if {@literal commons-logging} is directly excluded from
209+
* {@literal spring-core} then it is also transitive exclude on
210+
* {@literal spring-context} (since {@literal spring-context} depends on
211+
* {@literal spring-core}).
212+
*/
213+
TRANSITIVE
214+
215+
}
216+
191217
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.dependency.tools;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collections;
21+
import java.util.Iterator;
22+
import java.util.List;
23+
24+
/**
25+
* A single node in a {@link DependencyTree}.
26+
*
27+
* @author Phillip Webb
28+
* @see DependencyTree
29+
* @since 1.1.0
30+
*/
31+
class DependencyNode implements Iterable<DependencyNode> {
32+
33+
private final String groupId;
34+
35+
private final String artifactId;
36+
37+
private final String version;
38+
39+
private List<DependencyNode> dependencies;
40+
41+
DependencyNode(String groupId, String artifactId, String version) {
42+
this.groupId = groupId;
43+
this.artifactId = artifactId;
44+
this.version = version;
45+
this.dependencies = new ArrayList<DependencyNode>();
46+
}
47+
48+
@Override
49+
public Iterator<DependencyNode> iterator() {
50+
return getDependencies().iterator();
51+
}
52+
53+
public String getGroupId() {
54+
return this.groupId;
55+
}
56+
57+
public String getArtifactId() {
58+
return this.artifactId;
59+
}
60+
61+
public String getVersion() {
62+
return this.version;
63+
}
64+
65+
public List<DependencyNode> getDependencies() {
66+
return Collections.unmodifiableList(this.dependencies);
67+
}
68+
69+
@Override
70+
public String toString() {
71+
return this.groupId + ":" + this.artifactId + ":" + this.version;
72+
}
73+
74+
void addDependency(DependencyNode node) {
75+
this.dependencies.add(node);
76+
}
77+
78+
DependencyNode getLastDependency() {
79+
return this.dependencies.get(this.dependencies.size() - 1);
80+
}
81+
82+
}

0 commit comments

Comments
 (0)