Implement simpler exclusion logic for Gradle

Simplify the exclusion logic used in Gradle by implementing implicit
exclusions rather than trying to detect transitive excludes.

This commit reverts much of the code originally included to fix gh-1047
which adds far too much complexity to the build and still doesn't solve
the underlying issue.

Fixes gh-1103
pull/1116/head
Phillip Webb 11 years ago
parent f83c6aa7c1
commit 3a8a127285

@ -105,12 +105,8 @@
<skipTests>true</skipTests> <skipTests>true</skipTests>
</properties> </properties>
<modules> <modules>
<module>spring-boot-dependencies</module>
<module>spring-boot-versions</module> <module>spring-boot-versions</module>
<module>spring-boot-parent</module> <module>spring-boot-parent</module>
<module>spring-boot</module>
<module>spring-boot-autoconfigure</module>
<module>spring-boot-actuator</module>
<module>spring-boot-starters</module> <module>spring-boot-starters</module>
<module>spring-boot-tools</module> <module>spring-boot-tools</module>
</modules> </modules>

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>

@ -296,8 +296,7 @@ which does not have an `exclusion` element.
To ensure that correct exclusions are actually applied, the Spring Boot Gradle plugin will To ensure that correct exclusions are actually applied, the Spring Boot Gradle plugin will
automatically add exclusion rules. All exclusions defined in the automatically add exclusion rules. All exclusions defined in the
`spring-boot-dependencies` POM and the ``starter'' POMs will be added (both direct and `spring-boot-dependencies` POM and implicit rules for the ``starter'' POMs will be added.
transitive exclusions).
If you don't want exclusion rules automatically applied you can use the following If you don't want exclusion rules automatically applied you can use the following
configuration: configuration:

@ -54,6 +54,7 @@ public class WarPackagingTests {
Arrays.asList(WEB_INF_LIB_PROVIDED_PREFIX + "spring-boot-starter-jetty-", Arrays.asList(WEB_INF_LIB_PROVIDED_PREFIX + "spring-boot-starter-jetty-",
WEB_INF_LIB_PROVIDED_PREFIX + "jetty-util-", WEB_INF_LIB_PROVIDED_PREFIX + "jetty-util-",
WEB_INF_LIB_PROVIDED_PREFIX + "jetty-xml-", WEB_INF_LIB_PROVIDED_PREFIX + "jetty-xml-",
WEB_INF_LIB_PROVIDED_PREFIX + "javax.servlet-",
WEB_INF_LIB_PROVIDED_PREFIX + "jetty-continuation-", WEB_INF_LIB_PROVIDED_PREFIX + "jetty-continuation-",
WEB_INF_LIB_PROVIDED_PREFIX + "jetty-io-", WEB_INF_LIB_PROVIDED_PREFIX + "jetty-io-",
WEB_INF_LIB_PROVIDED_PREFIX + "jetty-http-", WEB_INF_LIB_PROVIDED_PREFIX + "jetty-http-",

@ -20,7 +20,6 @@
<main.basedir>${basedir}/..</main.basedir> <main.basedir>${basedir}/..</main.basedir>
</properties> </properties>
<modules> <modules>
<!-- If you add a starter remember to also add a dependency in spring-boot-versions -->
<module>spring-boot-starter</module> <module>spring-boot-starter</module>
<module>spring-boot-starter-amqp</module> <module>spring-boot-starter-amqp</module>
<module>spring-boot-starter-aop</module> <module>spring-boot-starter-aop</module>

@ -30,7 +30,7 @@
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<id>copy-resources</id> <id>copy-effective-pom</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
<goals> <goals>
<goal>copy</goal> <goal>copy</goal>
@ -46,15 +46,6 @@
<outputDirectory>${generated.pom.dir}</outputDirectory> <outputDirectory>${generated.pom.dir}</outputDirectory>
<destFileName>effective-pom.xml</destFileName> <destFileName>effective-pom.xml</destFileName>
</artifactItem> </artifactItem>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-versions</artifactId>
<version>${project.version}</version>
<type>dependency-tree</type>
<overWrite>true</overWrite>
<outputDirectory>${generated.pom.dir}</outputDirectory>
<destFileName>dependency-tree.txt</destFileName>
</artifactItem>
</artifactItems> </artifactItems>
</configuration> </configuration>
</execution> </execution>

@ -1,131 +0,0 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.dependency.tools;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.boot.dependency.tools.Dependency.Exclusion;
import org.springframework.boot.dependency.tools.Dependency.ExclusionType;
/**
* {@link Dependencies} to extend an existing {@link Dependencies} instance with
* transitive {@link Exclusion}s located from a {@link DependencyTree}.
*
* @author Phillip Webb
* @since 1.1.0
*/
class DependenciesWithTransitiveExclusions extends AbstractDependencies {
public DependenciesWithTransitiveExclusions(Dependencies dependencies,
DependencyTree tree) {
DependencyBuilder builder = new DependencyBuilder(dependencies);
builder.addTransitiveExcludes(tree);
builder.finish();
}
/**
* Builder used to collect the transitive exclusions.
*/
private class DependencyBuilder {
private Map<ArtifactAndGroupId, DependencyAndTransitiveExclusions> dependencies;
public DependencyBuilder(Dependencies dependencies) {
this.dependencies = new LinkedHashMap<ArtifactAndGroupId, DependencyAndTransitiveExclusions>();
for (Dependency dependency : dependencies) {
this.dependencies.put(new ArtifactAndGroupId(dependency),
new DependencyAndTransitiveExclusions(dependency));
}
}
public void addTransitiveExcludes(DependencyTree tree) {
for (DependencyNode node : tree) {
DependencyAndTransitiveExclusions dependency = this.dependencies
.get(asArtifactAndGroupId(node));
if (dependency != null) {
for (DependencyNode child : node) {
addTransitiveExcludes(dependency, child);
}
}
}
}
private void addTransitiveExcludes(DependencyAndTransitiveExclusions dependency,
DependencyNode node) {
DependencyAndTransitiveExclusions exclusions = this.dependencies
.get(asArtifactAndGroupId(node));
if (exclusions != null) {
dependency.addTransitiveExclusions(exclusions.getSourceDependency());
}
for (DependencyNode child : node) {
addTransitiveExcludes(dependency, child);
}
}
private ArtifactAndGroupId asArtifactAndGroupId(DependencyNode node) {
return new ArtifactAndGroupId(node.getGroupId(), node.getArtifactId());
}
public void finish() {
for (Map.Entry<ArtifactAndGroupId, DependencyAndTransitiveExclusions> entry : this.dependencies
.entrySet()) {
add(entry.getKey(), entry.getValue().createNewDependency());
}
}
}
/**
* Holds a {@link Dependency} with additional transitive {@link Exclusion}s.
*/
private static class DependencyAndTransitiveExclusions {
private Dependency dependency;
private Set<Exclusion> transitiveExclusions = new LinkedHashSet<Exclusion>();
public DependencyAndTransitiveExclusions(Dependency dependency) {
this.dependency = dependency;
}
public Dependency getSourceDependency() {
return this.dependency;
}
public void addTransitiveExclusions(Dependency dependency) {
for (Exclusion exclusion : dependency.getExclusions()) {
this.transitiveExclusions.add(new Exclusion(exclusion.getGroupId(),
exclusion.getArtifactId(), ExclusionType.TRANSITIVE));
}
}
public Dependency createNewDependency() {
Set<Exclusion> exclusions = new LinkedHashSet<Dependency.Exclusion>();
exclusions.addAll(this.dependency.getExclusions());
exclusions.addAll(this.transitiveExclusions);
return new Dependency(this.dependency.getGroupId(),
this.dependency.getArtifactId(), this.dependency.getVersion(),
new ArrayList<Exclusion>(exclusions));
}
}
}

@ -137,15 +137,11 @@ public final class Dependency {
private final String artifactId; private final String artifactId;
private final ExclusionType type; Exclusion(String groupId, String artifactId) {
Exclusion(String groupId, String artifactId, ExclusionType type) {
Assert.notNull(groupId, "GroupId must not be null"); Assert.notNull(groupId, "GroupId must not be null");
Assert.notNull(groupId, "ArtifactId must not be null"); Assert.notNull(groupId, "ArtifactId must not be null");
Assert.notNull(type, "Type must not be null");
this.groupId = groupId; this.groupId = groupId;
this.artifactId = artifactId; this.artifactId = artifactId;
this.type = type;
} }
/** /**
@ -162,10 +158,6 @@ public final class Dependency {
return this.groupId; return this.groupId;
} }
public ExclusionType getType() {
return this.type;
}
@Override @Override
public String toString() { public String toString() {
return this.groupId + ":" + this.artifactId; return this.groupId + ":" + this.artifactId;
@ -196,22 +188,4 @@ public final class Dependency {
} }
public static enum ExclusionType {
/**
* An exclusion that was specified directly on the dependency.
*/
DIRECT,
/**
* An exclusion that is was specified on a dependency of this dependency. For
* example if {@literal commons-logging} is directly excluded from
* {@literal spring-core} then it is also transitive exclude on
* {@literal spring-context} (since {@literal spring-context} depends on
* {@literal spring-core}).
*/
TRANSITIVE
}
} }

@ -1,82 +0,0 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.dependency.tools;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* A single node in a {@link DependencyTree}.
*
* @author Phillip Webb
* @see DependencyTree
* @since 1.1.0
*/
class DependencyNode implements Iterable<DependencyNode> {
private final String groupId;
private final String artifactId;
private final String version;
private List<DependencyNode> dependencies;
DependencyNode(String groupId, String artifactId, String version) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.dependencies = new ArrayList<DependencyNode>();
}
@Override
public Iterator<DependencyNode> iterator() {
return getDependencies().iterator();
}
public String getGroupId() {
return this.groupId;
}
public String getArtifactId() {
return this.artifactId;
}
public String getVersion() {
return this.version;
}
public List<DependencyNode> getDependencies() {
return Collections.unmodifiableList(this.dependencies);
}
@Override
public String toString() {
return this.groupId + ":" + this.artifactId + ":" + this.version;
}
void addDependency(DependencyNode node) {
this.dependencies.add(node);
}
DependencyNode getLastDependency() {
return this.dependencies.get(this.dependencies.size() - 1);
}
}

@ -1,159 +0,0 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.dependency.tools;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Dependency tree information that can be loaded from the output of
* {@literal mvn dependency:tree}.
*
* @author Phillip Webb
* @since 1.1.0
* @see DependencyNode
*/
class DependencyTree implements Iterable<DependencyNode> {
private final DependencyNode root;
/**
* Create a new {@link DependencyTree} instance for the given input stream.
* @param inputStream input stream containing content from
* {@literal mvn dependency:tree} (the stream will be closed).
*/
public DependencyTree(InputStream inputStream) {
try {
this.root = parse(inputStream);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
private DependencyNode parse(InputStream inputStream) throws IOException {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
Parser parser = new Parser();
String line;
while ((line = reader.readLine()) != null) {
parser.append(line);
}
return parser.getRoot();
}
finally {
inputStream.close();
}
}
@Override
public Iterator<DependencyNode> iterator() {
return getDependencies().iterator();
}
/**
* @return the root node for the tree.
*/
public DependencyNode getRoot() {
return this.root;
}
/**
* @return the dependencies of the root node.
*/
public List<DependencyNode> getDependencies() {
return this.root.getDependencies();
}
/**
* Return the node at the specified index.
* @param index the index (multiple indexes can be used to traverse the tree)
* @return the node at the specified index
*/
public DependencyNode get(int... index) {
DependencyNode rtn = this.root;
for (int i : index) {
rtn = rtn.getDependencies().get(i);
}
return rtn;
}
private static class Parser {
private static final int INDENT = 3;
private static final Set<Character> PREFIX_CHARS = new HashSet<Character>(
Arrays.asList(' ', '+', '-', '\\', '|'));
private static final Pattern LINE_PATTERN = Pattern
.compile("[(]?([^:]*):([^:]*):([^:]*):([^:\\s]*)");
private Deque<DependencyNode> stack = new ArrayDeque<DependencyNode>();
public void append(String line) {
int depth = getDepth(line);
String data = line.substring(depth * INDENT);
if (depth == 0) {
this.stack.push(createNode(data));
}
else {
while (depth < this.stack.size()) {
this.stack.pop();
}
if (depth > this.stack.size()) {
this.stack.push(this.stack.peek().getLastDependency());
}
this.stack.peek().addDependency(createNode(data));
}
}
private int getDepth(String line) {
for (int i = 0; i < line.length(); i++) {
if (!Parser.PREFIX_CHARS.contains(line.charAt(i))) {
return i / INDENT;
}
}
return 0;
}
private DependencyNode createNode(String line) {
Matcher matcher = LINE_PATTERN.matcher(line);
if (!matcher.find()) {
throw new IllegalStateException("Unable to parese line " + line);
}
return new DependencyNode(matcher.group(1), matcher.group(2),
matcher.group(4));
}
public DependencyNode getRoot() {
return this.stack.getLast();
}
}
}

@ -57,11 +57,7 @@ class ManagedDependenciesDelegate extends AbstractDependencies {
private static Dependencies getSpringBootDependencies() { private static Dependencies getSpringBootDependencies() {
if (springBootDependencies == null) { if (springBootDependencies == null) {
Dependencies dependencies = new PomDependencies( springBootDependencies = new PomDependencies(getResource("effective-pom.xml"));
getResource("effective-pom.xml"));
DependencyTree tree = new DependencyTree(getResource("dependency-tree.txt"));
dependencies = new DependenciesWithTransitiveExclusions(dependencies, tree);
springBootDependencies = dependencies;
} }
return springBootDependencies; return springBootDependencies;
} }

@ -25,7 +25,6 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import org.springframework.boot.dependency.tools.Dependency.Exclusion; import org.springframework.boot.dependency.tools.Dependency.Exclusion;
import org.springframework.boot.dependency.tools.Dependency.ExclusionType;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
@ -119,7 +118,7 @@ public class PomDependencies extends AbstractDependencies {
private Exclusion createExclusion(Element element) { private Exclusion createExclusion(Element element) {
String groupId = getTextContent(element, "groupId"); String groupId = getTextContent(element, "groupId");
String artifactId = getTextContent(element, "artifactId"); String artifactId = getTextContent(element, "artifactId");
return new Exclusion(groupId, artifactId, ExclusionType.DIRECT); return new Exclusion(groupId, artifactId);
} }
private String getTextContent(Element element, String tagName) { private String getTextContent(Element element, String tagName) {

@ -1,50 +0,0 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.dependency.tools;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link DependenciesWithTransitiveExclusions}.
*
* @author Phillip Webb
*/
public class DependenciesWithTransitiveExclusionsTests {
@Test
public void findsTransitiveExclusions() throws Exception {
Dependencies source = new PomDependencies(getClass().getResourceAsStream(
"test-effective-pom.xml"));
DependencyTree tree = new DependencyTree(getClass().getResourceAsStream(
"test-effective-pom-dependency-tree.txt"));
DependenciesWithTransitiveExclusions dependencies = new DependenciesWithTransitiveExclusions(
source, tree);
assertExcludes(dependencies, "sample01", "[org.exclude:exclude01]");
assertExcludes(source, "sample02", "[]");
assertExcludes(dependencies, "sample02", "[org.exclude:exclude01]");
}
private void assertExcludes(Dependencies dependencies, String artifactId,
String expected) {
Dependency dependency = dependencies.find("org.sample", artifactId);
assertThat(dependency.getExclusions().toString(), equalTo(expected));
}
}

@ -1,44 +0,0 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.dependency.tools;
import org.junit.Test;
import org.springframework.boot.dependency.tools.DependencyTree;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link DependencyTree}.
*
* @author Phillip Webb
*/
public class DependencyTreeTests {
@Test
public void parse() throws Exception {
DependencyTree tree = new DependencyTree(getClass().getResourceAsStream(
"sample-dependency-tree.txt"));
assertThat(tree.getRoot().toString(), equalTo("org.springframework.boot:"
+ "spring-boot-versions-dependency-tree:1.1.0.BUILD-SNAPSHOT"));
assertThat(tree.getDependencies().size(), equalTo(204));
assertThat(tree.get(0, 1).toString(), equalTo("org.slf4j:slf4j-api:1.7.6"));
assertThat(tree.get(203).toString(), equalTo("org.springframework.security:"
+ "spring-security-web:3.2.4.RELEASE"));
}
}

@ -1,5 +0,0 @@
org.sample:sample:pom:1.0.0.BUILD-SNAPSHOT
+- org.sample:sample01:jar:1.0.0:compile
+- org.sample:sample02:jar:1.0.0:compile
| +- (org.sample:sample01:jar:1.0.0:compile - omitted for duplicate)
\- org.springframework.boot:spring-boot:jar:1.0.0.BUILD-SNAPSHOT:compile

@ -2,8 +2,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version> <version>1.0.0.BUILD-SNAPSHOT</version>
<properties> <properties>
<sample.version>1.0.0</sample.version> <sample.version>1.0.0</sample.version>

@ -47,10 +47,12 @@ public class ApplyExcludeRules implements Action<Configuration> {
@Override @Override
public void execute(Configuration configuration) { public void execute(Configuration configuration) {
if (!VersionManagedDependencies.CONFIGURATION.equals(configuration.getName())) { if (!VersionManagedDependencies.CONFIGURATION.equals(configuration.getName())) {
configuration.getIncoming().beforeResolve(new Action<ResolvableDependencies>() { configuration.getIncoming().beforeResolve(
new Action<ResolvableDependencies>() {
@Override @Override
public void execute(ResolvableDependencies resolvableDependencies) { public void execute(ResolvableDependencies resolvableDependencies) {
resolvableDependencies.getDependencies().all(new Action<Dependency>() { resolvableDependencies.getDependencies().all(
new Action<Dependency>() {
@Override @Override
public void execute(Dependency dependency) { public void execute(Dependency dependency) {
applyExcludeRules(dependency); applyExcludeRules(dependency);
@ -73,13 +75,10 @@ public class ApplyExcludeRules implements Action<Configuration> {
org.springframework.boot.dependency.tools.Dependency managedDependency = managedDependencies org.springframework.boot.dependency.tools.Dependency managedDependency = managedDependencies
.find(dependency.getGroup(), dependency.getName()); .find(dependency.getGroup(), dependency.getName());
if (managedDependency != null) { if (managedDependency != null) {
if (managedDependency.getExclusions().isEmpty()) {
logger.debug("No exclusions rules applied for managed dependency "
+ dependency);
}
for (Exclusion exclusion : managedDependency.getExclusions()) { for (Exclusion exclusion : managedDependency.getExclusions()) {
addExcludeRule(dependency, exclusion); addExcludeRule(dependency, exclusion);
} }
addImplicitExcludeRules(dependency);
} }
else { else {
logger.debug("No exclusions rules applied for non-managed dependency " logger.debug("No exclusions rules applied for non-managed dependency "
@ -94,4 +93,21 @@ public class ApplyExcludeRules implements Action<Configuration> {
dependency.getExcludeRules().add(rule); dependency.getExcludeRules().add(rule);
} }
private void addImplicitExcludeRules(ModuleDependency dependency) {
if (isStarter(dependency)) {
logger.info("Adding implicit managed exclusion rules to starter "
+ dependency);
dependency.getExcludeRules().add(
new DefaultExcludeRule("commons-logging", "commons-logging"));
dependency.getExcludeRules().add(
new DefaultExcludeRule("commons-logging", "commons-logging-api"));
}
}
private boolean isStarter(ModuleDependency dependency) {
return (dependency.getGroup() != null
&& dependency.getGroup().equals("org.springframework.boot") && dependency
.getName().startsWith("spring-boot-starter"));
}
} }

@ -27,7 +27,6 @@
</resources> </resources>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId> <artifactId>maven-help-plugin</artifactId>
<executions> <executions>
<execution> <execution>
@ -42,49 +41,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>execute</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
<configuration>
<scripts>
<script>file:///${project.basedir}/src/main/groovy/generateDependencyTreePom.groovy</script>
</scripts>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<executions>
<execution>
<id>generate-dependency-tree</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<cloneProjectsTo>${project.build.directory}/invoker</cloneProjectsTo>
<settingsFile>src/dependency-tree/settings.xml</settingsFile>
<streamLogs>true</streamLogs>
<pom>${basedir}/src/dependency-tree/pom.xml</pom>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId> <artifactId>xml-maven-plugin</artifactId>
@ -131,10 +87,6 @@
<file>${project.build.directory}/effective-pom/spring-boot-versions.xml</file> <file>${project.build.directory}/effective-pom/spring-boot-versions.xml</file>
<type>effective-pom</type> <type>effective-pom</type>
</artifact> </artifact>
<artifact>
<file>${project.build.directory}/dependency-tree/dependency-tree.txt </file>
<type>dependency-tree</type>
</artifact>
</artifacts> </artifacts>
</configuration> </configuration>
</execution> </execution>
@ -142,138 +94,4 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-gemfire</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-groovy-templates</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hornetq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mobile</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-social-facebook</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-social-linkedin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-social-twitter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-velocity</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
</dependency>
</dependencies>
</project> </project>

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-versions</artifactId>
<version>@project.version@</version>
<relativePath>../../target/dependency-tree</relativePath>
</parent>
<artifactId>spring-boot-versions-dependency-tree</artifactId>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>write-dependencies-tree</id>
<phase>generate-resources</phase>
<goals>
<goal>tree</goal>
</goals>
<configuration>
<outputFile>@project.build.directory@/dependency-tree/dependency-tree.txt</outputFile>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-ext</id>
<url>http://repo.spring.io/ext-release-local/</url>
</repository>
</repositories>
</project>

@ -1,34 +0,0 @@
// Generate a POM from the effective-pom that can be used to build a complete dependency tree
import groovy.util.*
import groovy.xml.*
def effectivePom = new XmlSlurper().parse(
new File(project.build.directory, 'effective-pom/spring-boot-versions.xml'))
effectivePom.dependencyManagement.dependencies.dependency.findAll{ it.groupId != "org.springframework.boot" }.each {
effectivePom.dependencies.appendNode( it )
}
// effectivePom.appendNode(effectivePom.dependencyManagement.dependencies)
effectivePom.parent.replaceNode {}
effectivePom.dependencyManagement.replaceNode {}
effectivePom.build.replaceNode {}
effectivePom.properties.replaceNode {}
effectivePom.repositories.replaceNode {}
effectivePom.pluginRepositories.replaceNode {}
effectivePom.reporting.replaceNode {}
out = new StreamingMarkupBuilder()
String xmlResult = out.bind {
mkp.declareNamespace("": "http://maven.apache.org/POM/4.0.0")
mkp.yield effectivePom
}
def outputDir = new File(project.build.directory, 'dependency-tree');
outputDir.mkdirs();
XmlUtil.serialize(xmlResult, new FileWriter(new File(outputDir, 'pom.xml')))
Loading…
Cancel
Save