IVY-1667: makepom: check output lines for dependencyManagement element

This commit is contained in:
Eric Milles 2026-06-12 11:24:44 -05:00
parent 8ca1d8895e
commit 0dc2b2d237
Failed to extract signature
2 changed files with 219 additions and 68 deletions

View File

@ -72,22 +72,18 @@ public final class PomModuleDescriptorWriter {
throws IOException {
LineNumberReader in;
if (options.getTemplate() == null) {
in = new LineNumberReader(new InputStreamReader(
PomModuleDescriptorWriter.class.getResourceAsStream("pom.template")));
in = new LineNumberReader(new InputStreamReader(PomModuleDescriptorWriter.class.getResourceAsStream("pom.template")));
} else {
in = new LineNumberReader(new InputStreamReader(new FileInputStream(
options.getTemplate())));
in = new LineNumberReader(new InputStreamReader(new FileInputStream(options.getTemplate())));
}
if (output.getParentFile() != null) {
output.getParentFile().mkdirs();
}
PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output),
StandardCharsets.UTF_8));
try {
try (PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), StandardCharsets.UTF_8))) {
IvySettings settings = IvyContext.getContext().getSettings();
IvyVariableContainer variables = new IvyVariableContainerWrapper(
settings.getVariableContainer());
IvyVariableContainer variables = new IvyVariableContainerWrapper(settings.getVariableContainer());
variables.setVariable("ivy.pom.license", SKIP_LINE, true);
variables.setVariable("ivy.pom.header", SKIP_LINE, true);
@ -103,53 +99,56 @@ public final class PomModuleDescriptorWriter {
variables.setVariable("ivy.pom.license", options.getLicenseHeader(), true);
}
if (options.isPrintIvyInfo()) {
String header = "<!--\n" + " Apache Maven 2 POM generated by Apache Ivy\n"
+ " " + Ivy.getIvyHomeURL() + "\n" + " Apache Ivy version: "
+ Ivy.getIvyVersion() + " " + Ivy.getIvyDate() + "\n" + "-->";
String header
= "<!--\n" // TODO: replace \n with lineSeparator()
+ " Apache Maven 2 POM generated by Apache Ivy\n"
+ " " + Ivy.getIvyHomeURL() + "\n"
+ " Apache Ivy version: " + Ivy.getIvyVersion() + " " + Ivy.getIvyDate() + "\n"
+ "-->";
variables.setVariable("ivy.pom.header", header, true);
}
setModuleVariables(md, variables, options);
boolean dependencyManagement = false;
boolean dependenciesPrinted = false;
int lastIndent = 0;
int indent = 0;
String line = in.readLine();
while (line != null) {
String line;
while ((line = in.readLine()) != null) {
line = IvyPatternHelper.substituteVariables(line, variables);
if (line.contains(SKIP_LINE)) {
// skip this line
line = in.readLine();
continue;
}
if (line.trim().isEmpty()) {
// empty line
out.println(line);
line = in.readLine();
continue;
if (!line.trim().isEmpty()) {
lastIndent = indent;
indent = line.indexOf('<');
if (line.contains("<dependencyManagement>")) {
dependencyManagement = true;
}
if (line.contains("</dependencyManagement>")) {
dependencyManagement = false;
}
if (line.contains("</dependencies>") && !dependenciesPrinted && !dependencyManagement) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
}
if (line.contains("</project>") && !dependenciesPrinted) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
}
}
lastIndent = indent;
indent = line.indexOf('<');
if (!dependenciesPrinted && line.contains("</dependencies>")) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
}
if (!dependenciesPrinted && line.contains("</project>")) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
}
out.println(line);
line = in.readLine();
}
} finally {
in.close();
out.close();
}
}

View File

@ -15,15 +15,10 @@
* limitations under the License.
*
*/
package org.apache.ivy.core.module.descriptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@ -32,59 +27,61 @@ import javax.xml.xpath.XPathConstants;
import org.apache.ivy.TestHelper;
import org.apache.ivy.ant.IvyMakePom;
import org.apache.ivy.util.TestXmlHelper;
import org.apache.tools.ant.Project;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeLines;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Tests {@link IvyMakePom}
* Tests {@link IvyMakePom}.
*/
public class IvyMakePomTest {
private Project project;
private Project project = TestHelper.newProject();
@Rule
public TemporaryFolder workdir = new TemporaryFolder();
@Before
public void beforeTest() {
this.project = TestHelper.newProject();
}
/**
* Test case for IVY-1528. An Ivy file containing a <code>classifier</code> extra attribute in
* its dependency, must retain the <code>classifier</code> in the generated POM when converted
* to a POM file through {@link IvyMakePom}.
*
* @throws Exception if something goes wrong
* @see <a href="https://issues.apache.org/jira/browse/IVY-1528">IVY-1528</a>
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1528">IVY-1528</a>.
* <p>
* An Ivy file containing a <code>classifier</code> extra attribute in its
* dependency, must retain the <code>classifier</code> in the generated POM
* when converted to a POM file through {@link IvyMakePom}.
*/
@Test
public void testClassifier() throws Exception {
final File ivyFile = new File(IvyMakePomTest.class.getResource("ivy-to-pom-classifier.xml").toURI());
File ivyFile = new File(IvyMakePomTest.class.getResource("ivy-to-pom-classifier.xml").toURI());
assertTrue(ivyFile + " is either missing or not a file", ivyFile.isFile());
final IvyMakePom makepom = new IvyMakePom();
makepom.setProject(project);
final File generatedPomFile = workdir.newFile("test-ivy-to-pom-classifier.pom");
makepom.setPomFile(generatedPomFile);
makepom.setIvyFile(ivyFile);
// run the task
makepom.execute();
File pomFile = workdir.newFile("test-ivy-to-pom-classifier.pom");
// read the generated pom
final NodeList dependencies = (NodeList) TestXmlHelper.evaluateXPathExpr(generatedPomFile, "/project/dependencies/dependency", XPathConstants.NODESET);
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setProject(project);
task.execute();
NodeList dependencies = (NodeList) TestXmlHelper.evaluateXPathExpr(pomFile, "/project/dependencies/dependency", XPathConstants.NODESET);
assertNotNull("Dependencies element wasn't found in the generated POM file", dependencies);
assertEquals("Unexpected number of dependencies in the generated POM file", 2, dependencies.getLength());
final Set<String> expectedPomArtifactIds = new HashSet<>();
Set<String> expectedPomArtifactIds = new HashSet<>();
expectedPomArtifactIds.add("foo");
expectedPomArtifactIds.add("bar");
for (int i = 0; i < dependencies.getLength(); i++) {
final PomDependency pomDependency = PomDependency.parse(dependencies.item(i));
PomDependency pomDependency = PomDependency.parse(dependencies.item(i));
assertNotNull("Dependency generated was null", pomDependency);
assertTrue("Unexpected dependency " + pomDependency, expectedPomArtifactIds.contains(pomDependency.artifactId));
// we no longer expect this, so remove it
@ -103,6 +100,161 @@ public class IvyMakePomTest {
assertTrue("Some expected dependencies " + expectedPomArtifactIds + " were not found in the generated POM file", expectedPomArtifactIds.isEmpty());
}
@Test
public void testMakePomWithTemplate() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
writeLines(ivyFile, "UTF-8", Arrays.asList(
"<ivy-module version='2.0'>",
" <info module='name' organisation='org' revision='1.0.0-SNAPSHOT' />",
" <configurations>",
" <conf name='default' />",
" </configurations>",
" <dependencies defaultconf='default' defaultconfmapping='*->master,runtime()'>",
" <dependency org='org.springframework' name='spring-aop' rev='6.2.9' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy.pom");
File templateFile = workdir.newFile("the.pom");
writeLines(templateFile, "UTF-8", Arrays.asList(
"<project>",
" <groupId>${ivy.pom.groupId}</groupId>",
" <artifactId>${ivy.pom.artifactId}</artifactId>",
" <version>${ivy.pom.version}</version>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>"
));
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
task.setTemplateFile(templateFile);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<project>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <version>1.0.0-SNAPSHOT</version>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>",
""
};
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
/**
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1667">IVY-1667</a>.
*/
@Test
public void testMakePomWithTemplate1667() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
writeLines(ivyFile, "UTF-8", Arrays.asList(
"<ivy-module version='2.0'>",
" <info module='name' organisation='org' revision='1.0.0-SNAPSHOT' />",
" <configurations>",
" <conf name='default' />",
" </configurations>",
" <dependencies defaultconf='default' defaultconfmapping='*->master,runtime()'>",
" <dependency org='org.springframework' name='spring-aop' rev='6.2.9' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy.pom");
File templateFile = workdir.newFile("the.pom");
writeLines(templateFile, "UTF-8", Arrays.asList(
"<project>",
" <groupId>${ivy.pom.groupId}</groupId>",
" <artifactId>${ivy.pom.artifactId}</artifactId>",
" <version>${ivy.pom.version}</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
"</project>"
));
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
task.setTemplateFile(templateFile);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<project>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <version>1.0.0-SNAPSHOT</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>",
""
};
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
//--------------------------------------------------------------------------
private static final class PomDependency {
private final String groupId;
private final String artifactId;