From 212c30f6c7b2cba7b4f17eb6fbf206eb963c4459 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 30 May 2014 18:14:27 +0100 Subject: [PATCH] Enhance DependencyCustomer: allow type and classifier to be specified Closes #1002 --- .../cli/compiler/DependencyCustomizer.java | 36 ++++++++++--- .../ArtifactCoordinatesResolver.java | 12 +++-- .../compiler/DependencyCustomizerTests.java | 53 ++++++++++++++----- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java index 6a5999f76d..680704451a 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java @@ -32,7 +32,7 @@ import org.springframework.boot.cli.compiler.dependencies.ArtifactCoordinatesRes *

* This class provides a fluent API for conditionally adding dependencies. For example: * {@code dependencies.ifMissing("com.corp.SomeClass").add(module)}. - * + * * @author Phillip Webb * @author Andy Wilkinson */ @@ -180,20 +180,21 @@ public class DependencyCustomizer { /** * Add dependencies and all of their dependencies. The group ID and version of the - * dependency are resolves using the customizer's {@link ArtifactCoordinatesResolver}. + * dependencies are resolved from the modules using the customizer's + * {@link ArtifactCoordinatesResolver}. * @param modules The module IDs * @return this {@link DependencyCustomizer} for continued use */ public DependencyCustomizer add(String... modules) { for (String module : modules) { - add(module, true); + add(module, null, null, true); } return this; } /** * Add a single dependency and, optionally, all of its dependencies. The group ID and - * version of the dependency are resolves using the customizer's + * version of the dependency are resolved from the module using the customizer's * {@link ArtifactCoordinatesResolver}. * @param module The module ID * @param transitive {@code true} if the transitive dependencies should also be added, @@ -201,23 +202,46 @@ public class DependencyCustomizer { * @return this {@link DependencyCustomizer} for continued use */ public DependencyCustomizer add(String module, boolean transitive) { + return add(module, null, null, transitive); + } + + /** + * Add a single dependency with the specified classifier and type and, optionally, all + * of its dependencies. The group ID and version of the dependency are resolved from + * the module by using the customizer's {@link ArtifactCoordinatesResolver}. + * @param module The module ID + * @param classifier The classifier, may be {@code null} + * @param type The type, may be {@code null} + * @param transitive {@code true} if the transitive dependencies should also be added, + * otherwise {@code false}. + * @return this {@link DependencyCustomizer} for continued use + */ + public DependencyCustomizer add(String module, String classifier, String type, + boolean transitive) { if (canAdd()) { ArtifactCoordinatesResolver artifactCoordinatesResolver = this.dependencyResolutionContext .getArtifactCoordinatesResolver(); this.classNode.addAnnotation(createGrabAnnotation( artifactCoordinatesResolver.getGroupId(module), artifactCoordinatesResolver.getArtifactId(module), - artifactCoordinatesResolver.getVersion(module), transitive)); + artifactCoordinatesResolver.getVersion(module), classifier, type, + transitive)); } return this; } private AnnotationNode createGrabAnnotation(String group, String module, - String version, boolean transitive) { + String version, String classifier, String type, boolean transitive) { AnnotationNode annotationNode = new AnnotationNode(new ClassNode(Grab.class)); annotationNode.addMember("group", new ConstantExpression(group)); annotationNode.addMember("module", new ConstantExpression(module)); annotationNode.addMember("version", new ConstantExpression(version)); + if (classifier != null) { + annotationNode.addMember("classifier", new ConstantExpression(classifier)); + } + if (type != null) { + annotationNode.addMember("type", new ConstantExpression(type)); + } annotationNode.addMember("transitive", new ConstantExpression(transitive)); annotationNode.addMember("initClass", new ConstantExpression(false)); return annotationNode; diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/dependencies/ArtifactCoordinatesResolver.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/dependencies/ArtifactCoordinatesResolver.java index 49b17b39b6..dcf5755fe3 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/dependencies/ArtifactCoordinatesResolver.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/dependencies/ArtifactCoordinatesResolver.java @@ -17,9 +17,13 @@ package org.springframework.boot.cli.compiler.dependencies; /** - * A resolver for artifacts' Maven coordinates, allowing a group id or version to be - * obtained from an artifact ID. - * + * A resolver for artifacts' Maven coordinates, allowing group id, artifact id, or version + * to be obtained from a module identifier. A module identifier may be in the form + * {@code groupId:artifactId:version}, in which case coordinate resolution simply extracts + * the relevant piece from the identifier. Alternatively the identifier may be in the form + * {@code artifactId}, in which case coordinate resolution uses implementation-specific + * metadata to resolve the groupId and version. + * * @author Andy Wilkinson */ public interface ArtifactCoordinatesResolver { @@ -36,7 +40,7 @@ public interface ArtifactCoordinatesResolver { * Gets the artifact id of the artifact identified by the given {@code module}. * Returns {@code null} if the artifact is unknown to the resolver. * @param module The id of the module - * @return The group id of the module + * @return The artifact id of the module */ String getArtifactId(String module); diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/DependencyCustomizerTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/DependencyCustomizerTests.java index fe4338d2e2..e86a4a7202 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/DependencyCustomizerTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/DependencyCustomizerTests.java @@ -33,6 +33,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.boot.cli.compiler.dependencies.ArtifactCoordinatesResolver; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.when; /** @@ -75,7 +76,30 @@ public class DependencyCustomizerTests { assertEquals(1, grabAnnotations.size()); AnnotationNode annotationNode = grabAnnotations.get(0); assertGrabAnnotation(annotationNode, "org.springframework.boot", - "spring-boot-starter-logging", true); + "spring-boot-starter-logging", "1.2.3", null, null, true); + } + + @Test + public void nonTransitiveAdd() { + this.dependencyCustomizer.add("spring-boot-starter-logging", false); + List grabAnnotations = this.classNode + .getAnnotations(new ClassNode(Grab.class)); + assertEquals(1, grabAnnotations.size()); + AnnotationNode annotationNode = grabAnnotations.get(0); + assertGrabAnnotation(annotationNode, "org.springframework.boot", + "spring-boot-starter-logging", "1.2.3", null, null, false); + } + + @Test + public void fullyCustomized() { + this.dependencyCustomizer.add("spring-boot-starter-logging", "my-classifier", + "my-type", false); + List grabAnnotations = this.classNode + .getAnnotations(new ClassNode(Grab.class)); + assertEquals(1, grabAnnotations.size()); + AnnotationNode annotationNode = grabAnnotations.get(0); + assertGrabAnnotation(annotationNode, "org.springframework.boot", + "spring-boot-starter-logging", "1.2.3", "my-classifier", "my-type", false); } @Test @@ -120,21 +144,24 @@ public class DependencyCustomizerTests { assertEquals(1, this.classNode.getAnnotations(new ClassNode(Grab.class)).size()); } - @Test - public void nonTransitiveAdd() { - this.dependencyCustomizer.add("spring-boot-starter-logging", false); - List grabAnnotations = this.classNode - .getAnnotations(new ClassNode(Grab.class)); - assertEquals(1, grabAnnotations.size()); - AnnotationNode annotationNode = grabAnnotations.get(0); - assertGrabAnnotation(annotationNode, "org.springframework.boot", - "spring-boot-starter-logging", false); - } - private void assertGrabAnnotation(AnnotationNode annotationNode, String group, - String module, boolean transitive) { + String module, String version, String classifier, String type, + boolean transitive) { assertEquals(group, getMemberValue(annotationNode, "group")); assertEquals(module, getMemberValue(annotationNode, "module")); + assertEquals(version, getMemberValue(annotationNode, "version")); + if (type == null) { + assertNull(annotationNode.getMember("type")); + } + else { + assertEquals(type, getMemberValue(annotationNode, "type")); + } + if (classifier == null) { + assertNull(annotationNode.getMember("classifier")); + } + else { + assertEquals(classifier, getMemberValue(annotationNode, "classifier")); + } assertEquals(transitive, getMemberValue(annotationNode, "transitive")); }