diff --git a/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java b/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java index c1accb8a..87690f00 100644 --- a/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java +++ b/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java @@ -335,11 +335,12 @@ public class PomModuleDescriptorBuilder { if (dep.getClassifier() != null) { extraAtt.put("m:classifier", dep.getClassifier()); } - DefaultDependencyArtifactDescriptor depArtifact = new DefaultDependencyArtifactDescriptor( + final DefaultDependencyArtifactDescriptor depArtifact = new DefaultDependencyArtifactDescriptor( dd, dd.getDependencyId().getName(), type, ext, null, extraAtt); // here we have to assume a type and ext for the artifact, so this is a limitation // compared to how m2 behave with classifiers - String optionalizedScope = dep.isOptional() ? "optional" : scope; + final String optionalizedScope = dep.isOptional() ? "optional" : scope; + depArtifact.addConfiguration(optionalizedScope); dd.addDependencyArtifact(optionalizedScope, depArtifact); } diff --git a/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java b/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java index 5ddaff37..44825b88 100644 --- a/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java +++ b/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java @@ -272,9 +272,11 @@ public final class XmlModuleDescriptorWriter { XMLHelper.escape(depArtifact.getName()), XMLHelper.escape(depArtifact.getType()), XMLHelper.escape(depArtifact.getExt()))); - String[] dadConfs = depArtifact.getConfigurations(); - if (!Arrays.asList(dadConfs).equals(Arrays.asList(md.getConfigurationsNames()))) { - out.print(listToPrefixedString(dadConfs, " conf=\"")); + final String[] dadConfs = depArtifact.getConfigurations(); + if (dadConfs != null && dadConfs.length > 0) { + if (!Arrays.asList(dadConfs).equals(Arrays.asList(md.getConfigurationsNames()))) { + out.print(listToPrefixedString(dadConfs, " conf=\"")); + } } printExtraAttributes(depArtifact, out, " "); out.println("/>"); diff --git a/test/java/org/apache/ivy/core/resolve/ResolveTest.java b/test/java/org/apache/ivy/core/resolve/ResolveTest.java index 8d2fea3c..abeae456 100644 --- a/test/java/org/apache/ivy/core/resolve/ResolveTest.java +++ b/test/java/org/apache/ivy/core/resolve/ResolveTest.java @@ -6523,6 +6523,72 @@ public class ResolveTest { } + + /** + * Tests the issue noted in IVY-1586. + *
+ * org.apache:1586:1.0.0 depends on (Maven modules): + * -> org.apache:1580-foo-api:1.2.3 + * -> org.apache:1580-foo-impl:1.2.3 conf="default", which in turn depends on: + * -> org.apache:1580-foo-api:1.2.3 (in compile scope) + * -> org.apache:1580-foo-api:1.2.3 (type = test-jar, in test scope) + *+ * It's expected that the resolution of org.apache:1586:1.0.0, gets the + * "jar" type of org.apache:1580-foo-api and not the test-jar of the same org.apache:1580-foo-api, + * since only the "default" conf is demanded via the org.apache:1580-foo-impl:1.2.3 dependency. + * + * @see IVY-1586 + * + * @throws Exception + */ + @Test + public void testIvy1586() throws Exception { + // do it twice (once in fresh cache and once with the cache populated) + for (int i = 0; i < 2; i++) { + if (i == 0) { + ivy.getLoggerEngine().info("ResolveTest#testIvy1586 - Using a clean Ivy cache"); + } else { + ivy.getLoggerEngine().info("ResolveTest#testIvy1586 - Using an already populated Ivy cache"); + } + final File ivyXML = new File("test/repositories/1/ivy-1586/ivy-1586.xml"); + final ResolveReport resolveReport = ivy.resolve(ivyXML.toURI().toURL(), + new ResolveOptions().setConfs(new String[]{"*"})); + assertFalse("Resolution report has failures", resolveReport.hasError()); + final String rootModuleConf = "default"; + // get the "default" conf, resolution report for the org.apache:1586:1.0.0 module (represented by the + // ivy-1586.xml module descriptor) + final ConfigurationResolveReport confReport = resolveReport.getConfigurationReport(rootModuleConf); + assertNotNull(rootModuleConf + " conf resolution report for " + + resolveReport.getModuleDescriptor().getModuleRevisionId() + " is null", confReport); + + final ModuleRevisionId apiDependencyId = ModuleRevisionId.newInstance("org.apache", "1580-foo-api", "1.2.3"); + final IvyNode apiDepNode = confReport.getDependency(apiDependencyId); + assertNotNull("Dependency " + apiDependencyId + " not found in conf resolve report", apiDepNode); + final Artifact[] apiArtifacts = apiDepNode.getArtifacts(rootModuleConf); + assertNotNull("No artifacts available for dependency " + apiDependencyId, apiArtifacts); + assertEquals("Unexpected number of artifacts for dependency " + apiDependencyId, 1, apiArtifacts.length); + final Artifact apiArtifact = apiArtifacts[0]; + assertEquals("Unexpected artifact name", "1580-foo-api", apiArtifact.getName()); + assertEquals("Unexpected type for artifact", "jar", apiArtifact.getType()); + ArtifactDownloadReport apiDownloadReport = null; + for (final ArtifactDownloadReport artifactDownloadReport : confReport.getAllArtifactsReports()) { + if (artifactDownloadReport.getArtifact().equals(apiArtifact)) { + apiDownloadReport = artifactDownloadReport; + break; + } + } + assertNotNull("No download report found for artifact " + apiArtifact, apiDownloadReport); + final File apiJar = apiDownloadReport.getLocalFile(); + assertNotNull("artifact jar file is null for " + apiArtifact, apiJar); + assertJarContains(apiJar, "api-file.txt"); + + // just do some basic check on the impl module as well + final ModuleRevisionId implDepId = ModuleRevisionId.newInstance("org.apache", "1580-foo-impl", "1.2.3"); + final IvyNode implDepNode = confReport.getDependency(implDepId); + assertNotNull("Dependency " + implDepId + " not found in conf resolve report", implDepNode); + } + } + private void assertJarContains(final File jar, final String jarEntryPath) throws IOException { try (final JarFile jarFile = new JarFile(jar)) { final JarEntry entry = jarFile.getJarEntry(jarEntryPath); diff --git a/test/repositories/1/ivy-1586/ivy-1586.xml b/test/repositories/1/ivy-1586/ivy-1586.xml new file mode 100644 index 00000000..20454362 --- /dev/null +++ b/test/repositories/1/ivy-1586/ivy-1586.xml @@ -0,0 +1,27 @@ + + +