diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index 975d52145e..74f1bd37ab 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -31,16 +31,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Properties; -import java.util.ServiceLoader; -import java.util.Set; import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -109,6 +101,9 @@ import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.NoSuchRealmException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.interpolation.AbstractValueSource; +import org.codehaus.plexus.interpolation.BasicInterpolator; +import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.codehaus.plexus.logging.LoggerManager; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -611,8 +606,34 @@ private void commands(CliRequest cliRequest) { // Needed to make this method package visible to make writing a unit test possible // Maybe it's better to move some of those methods to separate class (SoC). - void properties(CliRequest cliRequest) { - populateProperties(cliRequest.commandLine, cliRequest.systemProperties, cliRequest.userProperties); + void properties(CliRequest cliRequest) throws Exception { + Properties paths = new Properties(); + if (cliRequest.topDirectory != null) { + paths.put("session.topDirectory", cliRequest.topDirectory.toString()); + } + if (cliRequest.rootDirectory != null) { + paths.put("session.rootDirectory", cliRequest.rootDirectory.toString()); + } + + populateProperties(cliRequest.commandLine, paths, cliRequest.systemProperties, cliRequest.userProperties); + + // now that we have properties, interpolate all arguments + BasicInterpolator interpolator = + createInterpolator(paths, cliRequest.systemProperties, cliRequest.userProperties); + CommandLine.Builder commandLineBuilder = new CommandLine.Builder(); + for (Option option : cliRequest.commandLine.getOptions()) { + if (!String.valueOf(CLIManager.SET_USER_PROPERTY).equals(option.getOpt())) { + List values = option.getValuesList(); + for (ListIterator it = values.listIterator(); it.hasNext(); ) { + it.set(interpolator.interpolate(it.next())); + } + } + commandLineBuilder.addOption(option); + } + for (String arg : cliRequest.commandLine.getArgList()) { + commandLineBuilder.addArg(interpolator.interpolate(arg)); + } + cliRequest.commandLine = commandLineBuilder.build(); } PlexusContainer container(CliRequest cliRequest) throws Exception { @@ -1506,7 +1527,9 @@ int calculateDegreeOfConcurrency(String threadConfiguration) { // Properties handling // ---------------------------------------------------------------------- - static void populateProperties(CommandLine commandLine, Properties systemProperties, Properties userProperties) { + static void populateProperties( + CommandLine commandLine, Properties paths, Properties systemProperties, Properties userProperties) + throws Exception { EnvironmentUtils.addEnvVars(systemProperties); // ---------------------------------------------------------------------- @@ -1517,7 +1540,6 @@ static void populateProperties(CommandLine commandLine, Properties systemPropert final Properties userSpecifiedProperties = commandLine.getOptionProperties(String.valueOf(CLIManager.SET_USER_PROPERTY)); - userSpecifiedProperties.forEach((prop, value) -> setCliProperty((String) prop, (String) value, userProperties)); SystemProperties.addSystemProperties(systemProperties); @@ -1533,17 +1555,38 @@ static void populateProperties(CommandLine commandLine, Properties systemPropert String mavenBuildVersion = CLIReportingUtils.createMavenVersionString(buildProperties); systemProperties.setProperty("maven.build.version", mavenBuildVersion); + + BasicInterpolator interpolator = + createInterpolator(paths, systemProperties, userProperties, userSpecifiedProperties); + for (Map.Entry e : userSpecifiedProperties.entrySet()) { + String name = (String) e.getKey(); + String value = interpolator.interpolate((String) e.getValue()); + userProperties.setProperty(name, value); + // ---------------------------------------------------------------------- + // I'm leaving the setting of system properties here as not to break + // the SystemPropertyProfileActivator. This won't harm embedding. jvz. + // ---------------------------------------------------------------------- + if (System.getProperty(name) == null) { + System.setProperty(name, value); + } + } } - private static void setCliProperty(String name, String value, Properties properties) { - properties.setProperty(name, value); - - // ---------------------------------------------------------------------- - // I'm leaving the setting of system properties here as not to break - // the SystemPropertyProfileActivator. This won't harm embedding. jvz. - // ---------------------------------------------------------------------- - - System.setProperty(name, value); + private static BasicInterpolator createInterpolator(Properties... properties) { + StringSearchInterpolator interpolator = new StringSearchInterpolator(); + interpolator.addValueSource(new AbstractValueSource(false) { + @Override + public Object getValue(String expression) { + for (Properties props : properties) { + Object val = props.getProperty(expression); + if (val != null) { + return val; + } + } + return null; + } + }); + return interpolator; } static class ExitException extends Exception { diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java index eea6a87f97..e9e90e7278 100644 --- a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java +++ b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java @@ -53,6 +53,7 @@ import static java.util.Arrays.asList; import static org.apache.maven.cli.MavenCli.performProfileActivation; import static org.apache.maven.cli.MavenCli.performProjectActivation; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; @@ -552,6 +553,38 @@ public void findRootProjectWithAttribute() { assertEquals(test, new DefaultRootLocator().findRoot(test.resolve("child"))); } + @Test + public void testPropertiesInterpolation() throws Exception { + // Arrange + CliRequest request = new CliRequest( + new String[] { + "-Dfoo=bar", + "-DvalFound=s${foo}i", + "-DvalNotFound=s${foz}i", + "-DvalRootDirectory=${session.rootDirectory}/.mvn/foo", + "-DvalTopDirectory=${session.topDirectory}/pom.xml", + "-f", + "${session.rootDirectory}/my-child", + "prefix:3.0.0:${foo}", + "validate" + }, + null); + request.rootDirectory = Paths.get("myRootDirectory"); + request.topDirectory = Paths.get("myTopDirectory"); + + // Act + cli.cli(request); + cli.properties(request); + + // Assert + assertThat(request.getUserProperties().getProperty("valFound"), is("sbari")); + assertThat(request.getUserProperties().getProperty("valNotFound"), is("s${foz}i")); + assertThat(request.getUserProperties().getProperty("valRootDirectory"), is("myRootDirectory/.mvn/foo")); + assertThat(request.getUserProperties().getProperty("valTopDirectory"), is("myTopDirectory/pom.xml")); + assertThat(request.getCommandLine().getOptionValue('f'), is("myRootDirectory/my-child")); + assertThat(request.getCommandLine().getArgs(), equalTo(new String[] {"prefix:3.0.0:bar", "validate"})); + } + private MavenProject createMavenProject(String groupId, String artifactId) { MavenProject project = new MavenProject(); project.setGroupId(groupId);