[MNG-6303] Interpolate all arguments using system and user supplied properties (#1062)

This commit is contained in:
Guillaume Nodet 2023-05-05 15:12:12 +02:00 committed by GitHub
parent 9b6d263bdb
commit a1fa3eb534
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 22 deletions

View File

@ -31,16 +31,8 @@
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; 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.function.Consumer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -109,6 +101,9 @@
import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException; import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 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.logging.LoggerManager;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 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 // 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). // Maybe it's better to move some of those methods to separate class (SoC).
void properties(CliRequest cliRequest) { void properties(CliRequest cliRequest) throws Exception {
populateProperties(cliRequest.commandLine, cliRequest.systemProperties, cliRequest.userProperties); 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<String> values = option.getValuesList();
for (ListIterator<String> 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 { PlexusContainer container(CliRequest cliRequest) throws Exception {
@ -1506,7 +1527,9 @@ int calculateDegreeOfConcurrency(String threadConfiguration) {
// Properties handling // 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); EnvironmentUtils.addEnvVars(systemProperties);
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -1517,7 +1540,6 @@ static void populateProperties(CommandLine commandLine, Properties systemPropert
final Properties userSpecifiedProperties = final Properties userSpecifiedProperties =
commandLine.getOptionProperties(String.valueOf(CLIManager.SET_USER_PROPERTY)); commandLine.getOptionProperties(String.valueOf(CLIManager.SET_USER_PROPERTY));
userSpecifiedProperties.forEach((prop, value) -> setCliProperty((String) prop, (String) value, userProperties));
SystemProperties.addSystemProperties(systemProperties); SystemProperties.addSystemProperties(systemProperties);
@ -1533,17 +1555,38 @@ static void populateProperties(CommandLine commandLine, Properties systemPropert
String mavenBuildVersion = CLIReportingUtils.createMavenVersionString(buildProperties); String mavenBuildVersion = CLIReportingUtils.createMavenVersionString(buildProperties);
systemProperties.setProperty("maven.build.version", mavenBuildVersion); systemProperties.setProperty("maven.build.version", mavenBuildVersion);
BasicInterpolator interpolator =
createInterpolator(paths, systemProperties, userProperties, userSpecifiedProperties);
for (Map.Entry<Object, Object> 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) { private static BasicInterpolator createInterpolator(Properties... properties) {
properties.setProperty(name, value); StringSearchInterpolator interpolator = new StringSearchInterpolator();
interpolator.addValueSource(new AbstractValueSource(false) {
// ---------------------------------------------------------------------- @Override
// I'm leaving the setting of system properties here as not to break public Object getValue(String expression) {
// the SystemPropertyProfileActivator. This won't harm embedding. jvz. for (Properties props : properties) {
// ---------------------------------------------------------------------- Object val = props.getProperty(expression);
if (val != null) {
System.setProperty(name, value); return val;
}
}
return null;
}
});
return interpolator;
} }
static class ExitException extends Exception { static class ExitException extends Exception {

View File

@ -53,6 +53,7 @@
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.apache.maven.cli.MavenCli.performProfileActivation; import static org.apache.maven.cli.MavenCli.performProfileActivation;
import static org.apache.maven.cli.MavenCli.performProjectActivation; 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.is;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.nullValue;
@ -552,6 +553,38 @@ public void findRootProjectWithAttribute() {
assertEquals(test, new DefaultRootLocator().findRoot(test.resolve("child"))); 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) { private MavenProject createMavenProject(String groupId, String artifactId) {
MavenProject project = new MavenProject(); MavenProject project = new MavenProject();
project.setGroupId(groupId); project.setGroupId(groupId);