Support bom-based dependency management in the CLI

Previously, the CLI’s dependency management used proprietary Properties
file-based metadata to configure its dependency management. Since
spring-boot-gradle-plugin’s move to using the separate dependency
management plugin the CLI was the only user of this format.

This commit updates the CLI to use Maven boms to configure its
dependency management. By default it uses the spring-boot-dependencies
bom. This configuration can be augmented and overridden using the new
@DependencyManagementBom annotation which replaces @GrabMetadata.

Closes gh-2688
Closes gh-2439
This commit is contained in:
Andy Wilkinson
2015-03-19 17:15:10 +00:00
parent 390e6fa690
commit 51c49b69c5
73 changed files with 1001 additions and 1624 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -17,8 +17,6 @@
package org.springframework.boot.cli;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import org.junit.After;
import org.junit.Before;
@@ -65,31 +63,25 @@ public class GrabCommandIntegrationTests {
}
@Test
public void duplicateGrabMetadataAnnotationsProducesAnError() throws Exception {
public void duplicateDependencyManagementBomAnnotationsProducesAnError()
throws Exception {
try {
this.cli.grab("duplicateGrabMetadata.groovy");
this.cli.grab("duplicateDependencyManagementBom.groovy");
fail();
}
catch (Exception ex) {
assertThat(ex.getMessage(),
containsString("Duplicate @GrabMetadata annotation"));
containsString("Duplicate @DependencyManagementBom annotation"));
}
}
@Test
public void customMetadata() throws Exception {
System.setProperty("grape.root", "target");
File testArtifactDir = new File("target/repository/test/test/1.0.0");
testArtifactDir.mkdirs();
File testArtifact = new File(testArtifactDir, "test-1.0.0.properties");
testArtifact.createNewFile();
PrintWriter writer = new PrintWriter(new FileWriter(testArtifact));
writer.println("javax.ejb\\:ejb-api=3.0");
writer.close();
this.cli.grab("customGrabMetadata.groovy", "--autoconfigure=false");
FileSystemUtils.copyRecursively(new File(
"src/test/resources/grab-samples/repository"), new File(
"target/repository"));
this.cli.grab("customDependencyManagement.groovy", "--autoconfigure=false");
assertTrue(new File("target/repository/javax/ejb/ejb-api/3.0").isDirectory());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -60,12 +60,17 @@ public class DependencyCustomizerTests {
"org.springframework.boot");
given(this.resolver.getArtifactId("spring-boot-starter-logging")).willReturn(
"spring-boot-starter-logging");
given(this.resolver.getVersion("spring-boot-starter-logging"))
.willReturn("1.2.3");
this.moduleNode.addClass(this.classNode);
this.dependencyCustomizer = new DependencyCustomizer(new GroovyClassLoader(
getClass().getClassLoader()), this.moduleNode,
new DependencyResolutionContext(this.resolver));
new DependencyResolutionContext() {
@Override
public ArtifactCoordinatesResolver getArtifactCoordinatesResolver() {
return DependencyCustomizerTests.this.resolver;
}
});
}
@Test
@@ -149,7 +154,6 @@ public class DependencyCustomizerTests {
boolean transitive) {
assertEquals(group, getMemberValue(annotationNode, "group"));
assertEquals(module, getMemberValue(annotationNode, "module"));
assertEquals(version, getMemberValue(annotationNode, "version"));
if (type == null) {
assertNull(annotationNode.getMember("type"));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -65,8 +65,14 @@ public final class ResolveDependencyCoordinatesTransformationTests {
private final ArtifactCoordinatesResolver coordinatesResolver = mock(ArtifactCoordinatesResolver.class);
private final DependencyResolutionContext resolutionContext = new DependencyResolutionContext(
this.coordinatesResolver);
private final DependencyResolutionContext resolutionContext = new DependencyResolutionContext() {
@Override
public ArtifactCoordinatesResolver getArtifactCoordinatesResolver() {
return ResolveDependencyCoordinatesTransformationTests.this.coordinatesResolver;
}
};
private final ASTTransformation transformation = new ResolveDependencyCoordinatesTransformation(
this.resolutionContext);
@@ -75,13 +81,12 @@ public final class ResolveDependencyCoordinatesTransformationTests {
public void setupExpectations() {
given(this.coordinatesResolver.getGroupId("spring-core")).willReturn(
"org.springframework");
given(this.coordinatesResolver.getVersion("spring-core")).willReturn("4.0.0.RC1");
}
@Test
public void transformationOfAnnotationOnImport() {
this.moduleNode.addImport(null, null, Arrays.asList(this.grabAnnotation));
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -89,7 +94,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
this.moduleNode.addStarImport("org.springframework.util",
Arrays.asList(this.grabAnnotation));
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -97,7 +102,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
this.moduleNode.addStaticImport(null, null, null,
Arrays.asList(this.grabAnnotation));
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -105,7 +110,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
this.moduleNode.addStaticStarImport(null, null,
Arrays.asList(this.grabAnnotation));
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -114,7 +119,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
packageNode.addAnnotation(this.grabAnnotation);
this.moduleNode.setPackage(packageNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -123,7 +128,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
classNode.addAnnotation(this.grabAnnotation);
this.moduleNode.addClass(classNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -141,7 +146,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
fieldNode.addAnnotation(this.grabAnnotation);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -153,7 +158,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
constructorNode.addAnnotation(this.grabAnnotation);
classNode.addMethod(constructorNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -166,7 +171,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
methodNode.addAnnotation(this.grabAnnotation);
classNode.addMethod(methodNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -181,7 +186,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
new Parameter[] { parameter }, new ClassNode[0], null);
classNode.addMethod(methodNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
@Test
@@ -202,7 +207,7 @@ public final class ResolveDependencyCoordinatesTransformationTests {
classNode.addMethod(methodNode);
assertGrabAnnotationHasBeenTransformation();
assertGrabAnnotationHasBeenTransformed();
}
private AnnotationNode createGrabAnnotation() {
@@ -212,12 +217,11 @@ public final class ResolveDependencyCoordinatesTransformationTests {
return annotationNode;
}
private void assertGrabAnnotationHasBeenTransformation() {
private void assertGrabAnnotationHasBeenTransformed() {
this.transformation.visit(new ASTNode[] { this.moduleNode }, this.sourceUnit);
assertEquals("org.springframework", getGrabAnnotationMemberAsString("group"));
assertEquals("spring-core", getGrabAnnotationMemberAsString("module"));
assertEquals("4.0.0.RC1", getGrabAnnotationMemberAsString("version"));
}
private Object getGrabAnnotationMemberAsString(String memberName) {

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2012-2015 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.cli.compiler.dependencies;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
/**
* Tests for {@link CompositeDependencyManagement}
*
* @author Andy Wilkinson
*/
@RunWith(MockitoJUnitRunner.class)
public class CompositeDependencyManagementTests {
@Mock
private DependencyManagement dependencyManagement1;
@Mock
private DependencyManagement dependencyManagement2;
@Test
public void unknownSpringBootVersion() {
given(this.dependencyManagement1.getSpringBootVersion()).willReturn(null);
given(this.dependencyManagement2.getSpringBootVersion()).willReturn(null);
assertThat(new CompositeDependencyManagement(this.dependencyManagement1,
this.dependencyManagement2).getSpringBootVersion(), is(nullValue()));
}
@Test
public void knownSpringBootVersion() {
given(this.dependencyManagement1.getSpringBootVersion()).willReturn("1.2.3");
given(this.dependencyManagement2.getSpringBootVersion()).willReturn("1.2.4");
assertThat(new CompositeDependencyManagement(this.dependencyManagement1,
this.dependencyManagement2).getSpringBootVersion(), is("1.2.3"));
}
@Test
public void unknownDependency() {
given(this.dependencyManagement1.find("artifact")).willReturn(null);
given(this.dependencyManagement2.find("artifact")).willReturn(null);
assertThat(new CompositeDependencyManagement(this.dependencyManagement1,
this.dependencyManagement2).find("artifact"), is(nullValue()));
}
@Test
public void knownDependency() {
given(this.dependencyManagement1.find("artifact")).willReturn(
new Dependency("test", "artifact", "1.2.3"));
given(this.dependencyManagement2.find("artifact")).willReturn(
new Dependency("test", "artifact", "1.2.4"));
assertThat(new CompositeDependencyManagement(this.dependencyManagement1,
this.dependencyManagement2).find("artifact"), is(new Dependency("test",
"artifact", "1.2.3")));
}
@Test
public void getDependencies() {
given(this.dependencyManagement1.getDependencies()).willReturn(
Arrays.asList(new Dependency("test", "artifact", "1.2.3")));
given(this.dependencyManagement2.getDependencies()).willReturn(
Arrays.asList(new Dependency("test", "artifact", "1.2.4")));
assertThat(
new CompositeDependencyManagement(this.dependencyManagement1,
this.dependencyManagement2).getDependencies(),
contains(new Dependency("test", "artifact", "1.2.3"), new Dependency(
"test", "artifact", "1.2.4")));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -18,8 +18,6 @@ package org.springframework.boot.cli.compiler.dependencies;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.dependency.tools.Dependency;
import org.springframework.boot.dependency.tools.ManagedDependencies;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
@@ -31,30 +29,32 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link ManagedDependenciesArtifactCoordinatesResolver}.
* Tests for {@link DependencyManagementArtifactCoordinatesResolver}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ManagedDependenciesArtifactCoordinatesResolverTests {
public class DependencyManagementArtifactCoordinatesResolverTests {
private ManagedDependencies dependencies;
private DependencyManagement dependencyManagement;
private ManagedDependenciesArtifactCoordinatesResolver resolver;
private DependencyManagementArtifactCoordinatesResolver resolver;
@Before
public void setup() {
this.dependencies = mock(ManagedDependencies.class);
given(this.dependencies.find("a1")).willReturn(new Dependency("g1", "a1", "0"));
given(this.dependencies.getSpringBootVersion()).willReturn("1");
this.resolver = new ManagedDependenciesArtifactCoordinatesResolver(
this.dependencies);
this.dependencyManagement = mock(DependencyManagement.class);
given(this.dependencyManagement.find("a1")).willReturn(
new Dependency("g1", "a1", "0"));
given(this.dependencyManagement.getSpringBootVersion()).willReturn("1");
this.resolver = new DependencyManagementArtifactCoordinatesResolver(
this.dependencyManagement);
}
@Test
public void getGroupIdForBootArtifact() throws Exception {
assertThat(this.resolver.getGroupId("spring-boot-something"),
equalTo("org.springframework.boot"));
verify(this.dependencies, never()).find(anyString());
verify(this.dependencyManagement, never()).find(anyString());
}
@Test
@@ -67,20 +67,4 @@ public class ManagedDependenciesArtifactCoordinatesResolverTests {
assertThat(this.resolver.getGroupId("a2"), nullValue());
}
@Test
public void getVersionForBootArtifact() throws Exception {
assertThat(this.resolver.getVersion("spring-boot-something"), equalTo("1"));
verify(this.dependencies, never()).find(anyString());
}
@Test
public void getVersionFound() throws Exception {
assertThat(this.resolver.getVersion("a1"), equalTo("0"));
}
@Test
public void getVersionNotFound() throws Exception {
assertThat(this.resolver.getVersion("a2"), nullValue());
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012-2015 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.cli.compiler.dependencies;
import org.junit.Test;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link SpringBootDependenciesDependencyManagement}
*
* @author Andy Wilkinson
*/
public class SpringBootDependenciesDependencyManagementTests {
private final DependencyManagement dependencyManagement = new SpringBootDependenciesDependencyManagement();
@Test
public void springBootVersion() {
assertThat(this.dependencyManagement.getSpringBootVersion(), is(notNullValue()));
}
@Test
public void find() {
Dependency dependency = this.dependencyManagement.find("spring-boot");
assertThat(dependency, is(notNullValue()));
assertThat(dependency.getGroupId(), is(equalTo("org.springframework.boot")));
assertThat(dependency.getArtifactId(), is(equalTo("spring-boot")));
}
@Test
public void getDependencies() {
assertThat(this.dependencyManagement.getDependencies(), is(not(empty())));
}
}

View File

@@ -1,53 +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.cli.compiler.grape;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.springframework.boot.dependency.tools.Dependency;
import org.springframework.boot.dependency.tools.ManagedDependencies;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ManagedDependenciesFactory}.
*
* @author Phillip Webb
*/
public class ManagedDependenciesFactoryTests {
@Test
public void getManagedDependencies() {
List<Dependency> dependencyList = new ArrayList<Dependency>();
dependencyList.add(new Dependency("g1", "a1", "1"));
dependencyList.add(new Dependency("g1", "a2", "1"));
ManagedDependencies dependencies = mock(ManagedDependencies.class);
given(dependencies.iterator()).willReturn(dependencyList.iterator());
ManagedDependenciesFactory factory = new ManagedDependenciesFactory(dependencies);
List<org.eclipse.aether.graph.Dependency> result = factory
.getManagedDependencies();
assertThat(result.size(), equalTo(2));
assertThat(result.get(0).toString(), equalTo("g1:a1:jar:1 (compile)"));
assertThat(result.get(1).toString(), equalTo("g1:a2:jar:1 (compile)"));
}
}