Repository: ant-ivy Updated Branches: refs/heads/master 4c6450f45 -> c07d659cf
IVY-1561 Take into account environment variable and system properties while evaluating property references in Maven pom.xml Project: http://git-wip-us.apache.org/repos/asf/ant-ivy/repo Commit: http://git-wip-us.apache.org/repos/asf/ant-ivy/commit/c07d659c Tree: http://git-wip-us.apache.org/repos/asf/ant-ivy/tree/c07d659c Diff: http://git-wip-us.apache.org/repos/asf/ant-ivy/diff/c07d659c Branch: refs/heads/master Commit: c07d659cf8f7b16452472da6052a1de326bcb6a4 Parents: 4c6450f Author: Jaikiran Pai <jaikiran....@gmail.com> Authored: Tue Jun 13 10:57:53 2017 +0530 Committer: Jaikiran Pai <jaikiran....@gmail.com> Committed: Tue Jun 13 11:03:14 2017 +0530 ---------------------------------------------------------------------- .../apache/ivy/plugins/parser/m2/PomReader.java | 17 +++- .../m2/PomModuleDescriptorParserTest.java | 81 ++++++++++++++++++++ .../parser/m2/test-system-properties.pom | 58 ++++++++++++++ 3 files changed, 154 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/c07d659c/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java b/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java index 93d128b..25745e6 100644 --- a/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java +++ b/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java @@ -30,6 +30,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Properties; import org.apache.ivy.core.IvyPatternHelper; import org.apache.ivy.core.module.descriptor.License; @@ -110,13 +111,13 @@ public class PomReader { private static final String PROFILE = "profile"; - private HashMap<String, String> properties = new HashMap<String, String>(); + private final Map<String, String> properties = new HashMap<String, String>(); private final Element projectElement; private final Element parentElement; - public PomReader(URL descriptorURL, Resource res) throws IOException, SAXException { + public PomReader(final URL descriptorURL, final Resource res) throws IOException, SAXException { InputStream stream = new AddDTDFilterInputStream( URLHandlerRegistry.getDefault().openStream(descriptorURL)); InputSource source = new InputSource(stream); @@ -146,6 +147,18 @@ public class PomReader { // ignore } } + // Both environment and system properties take precedence over properties set in + // pom.xml. So we pre-populate our properties with the environment and system properties + // here + for (final Map.Entry<String, String> envEntry : System.getenv().entrySet()) { + // Maven let's users use "env." prefix for environment variables + this.setProperty("env." + envEntry.getKey(), envEntry.getValue()); + } + // add system properties + final Properties sysProps = System.getProperties(); + for (final String sysProp : sysProps.stringPropertyNames()) { + this.setProperty(sysProp, sysProps.getProperty(sysProp)); + } } public boolean hasParent() { http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/c07d659c/test/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParserTest.java ---------------------------------------------------------------------- diff --git a/test/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParserTest.java b/test/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParserTest.java index ad80cf8..44c77e8 100644 --- a/test/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParserTest.java +++ b/test/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParserTest.java @@ -25,11 +25,18 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.ParseException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor; @@ -54,6 +61,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; public class PomModuleDescriptorParserTest extends AbstractModuleDescriptorParserTester { @@ -79,6 +87,9 @@ public class PomModuleDescriptorParserTest extends AbstractModuleDescriptorParse @Rule public ExpectedException expExc = ExpectedException.none(); + @Rule + public TemporaryFolder workDir = new TemporaryFolder(); + @Before public void setUp() { settings.setDictatorResolver(mockedResolver); @@ -1043,6 +1054,76 @@ public class PomModuleDescriptorParserTest extends AbstractModuleDescriptorParse dds[0].getDependencyRevisionId()); } + /** + * Tests that a pom.xml which has references to properties that are either set via environment variables or system + * properties, has its properties evaluated correctly. + * + * @throws Exception + * @see <a href="https://issues.apache.org/jira/browse/IVY-1561">IVY-1561</a> + */ + @Test + public void testSystemPropertyAndEnvReferences() throws Exception { + // the pom we are testing contains reference to a string called "env.THIS_WILL_BE_REPLACED_IN_TEST_BY_A_ENV_VAR". + // this piece of code replaces it to "env.someenvname" where someenvname is a environment variable we + // choose in this test case (after randomly picking it from the ones that are set). + // finally we created the updated pom content in a separate file and test against that file + final String envName = chooseSomeEnvVar(); + final URL originalPomFile = this.getClass().getResource("test-system-properties.pom"); + assertNotNull("Pom file to test, is missing", originalPomFile); + final List<String> pomContent = Files.readAllLines(Paths.get(originalPomFile.toURI()), Charset.forName("UTF-8")); + final List<String> replacedContent = new ArrayList<>(); + for (final String line : pomContent) { + replacedContent.add(line.replaceAll("THIS_WILL_BE_REPLACED_IN_TEST_BY_A_ENV_VAR", envName)); + } + // write the new pom contents into a separate file + final Path updatedPomFile = Paths.get(workDir.getRoot().toPath().toString(), "updated-test-system-properties.pom"); + Files.write(updatedPomFile, replacedContent, Charset.forName("UTF-8")); + + // now start testing + // we do 2 rounds of testing - one with a system property (referenced in the pom) set and once unset + boolean withSystemPropertiesSet = false; + try { + for (int i = 0; i < 2; i++) { + if (i == 1) { + System.setProperty("version.test.system.property.b", "1.2.3"); + withSystemPropertiesSet = true; + } + final ModuleDescriptor md = PomModuleDescriptorParser.getInstance().parseDescriptor(settings, updatedPomFile.toUri().toURL(), false); + assertNotNull("Module descriptor created from POM reader was null", md); + assertEquals("Unexpected module descriptor created by POM reader", + ModuleRevisionId.newInstance("foo.bar", "hello-world", "2.0.2"), + md.getModuleRevisionId()); + + final DependencyDescriptor[] dds = md.getDependencies(); + assertNotNull("No dependency descriptors found in module descriptor", dds); + assertEquals("Unexpected number of dependencies in module descriptor", 4, dds.length); + final Set<ModuleRevisionId> expectedDependencies = new HashSet<>(); + expectedDependencies.add(ModuleRevisionId.newInstance("aopalliance", "aopalliance", "1.0")); + final String commonsLoggingDepVersion = envName == null ? "${env.THIS_WILL_BE_REPLACED_IN_TEST_BY_A_ENV_VAR}" : System.getenv(envName); + expectedDependencies.add(ModuleRevisionId.newInstance("commons-logging", "commons-logging", commonsLoggingDepVersion)); + expectedDependencies.add(ModuleRevisionId.newInstance("foo.bar", "hello-world-api", "2.0.2")); + expectedDependencies.add(ModuleRevisionId.newInstance("a", "b", withSystemPropertiesSet ? "1.2.3" : "2.3.4")); + for (final DependencyDescriptor dd : dds) { + assertNotNull("Dependency was null in the dependencies", dd); + assertTrue("Unexpected dependency " + dd.getDependencyRevisionId() + " in module descriptor", expectedDependencies.remove(dd.getDependencyRevisionId())); + } + assertTrue("Following dependencies were missing from module descriptor " + expectedDependencies, expectedDependencies.isEmpty()); + } + } finally { + System.clearProperty("version.test.system.property.b"); + } + } + + private static String chooseSomeEnvVar() { + final Map<String, String> env = System.getenv(); + for (final Map.Entry<String, String> entry : env.entrySet()) { + if (entry.getKey() != null && entry.getValue() != null) { + return entry.getKey(); + } + } + return null; + } + private IvySettings createIvySettingsForParentLicenseTesting(final String parentPomFileName, final String parentOrgName, final String parentModuleName) throws Exception { final URL parentPomURL = this.getClass().getResource(parentPomFileName); http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/c07d659c/test/java/org/apache/ivy/plugins/parser/m2/test-system-properties.pom ---------------------------------------------------------------------- diff --git a/test/java/org/apache/ivy/plugins/parser/m2/test-system-properties.pom b/test/java/org/apache/ivy/plugins/parser/m2/test-system-properties.pom new file mode 100644 index 0000000..386105a --- /dev/null +++ b/test/java/org/apache/ivy/plugins/parser/m2/test-system-properties.pom @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You 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. + --> +<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> + <groupId>foo.bar</groupId> + <artifactId>hello-world</artifactId> + <packaging>jar</packaging> + <version>2.0.2</version> + + <properties> + <version.aopalliance>1.0</version.aopalliance> + <version.commons-logging>${env.THIS_WILL_BE_REPLACED_IN_TEST_BY_A_ENV_VAR}</version.commons-logging> + <version.test.system.property.b>2.3.4</version.test.system.property.b> + </properties> + + <dependencies> + <dependency> + <groupId>a</groupId> + <artifactId>b</artifactId> + <version>${version.test.system.property.b}</version> + </dependency> + + <dependency> + <groupId>aopalliance</groupId> + <artifactId>aopalliance</artifactId> + <version>${version.aopalliance}</version> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>${version.commons-logging}</version> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>hello-world-api</artifactId> + <version>${project.version}</version> + </dependency> + + </dependencies> +</project>