Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package org.apache.maven.api.plugin.testing;

import javax.xml.stream.XMLStreamException;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -71,6 +73,7 @@
import org.apache.maven.api.services.ArtifactInstaller;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.LocalRepositoryManager;
import org.apache.maven.api.services.MavenException;
import org.apache.maven.api.services.ProjectBuilder;
import org.apache.maven.api.services.ProjectManager;
import org.apache.maven.api.services.RepositoryFactory;
Expand Down Expand Up @@ -269,7 +272,23 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
.map(ConfigurationContainer::getConfiguration)
.orElseGet(() -> XmlNode.newInstance("config"));
List<XmlNode> children = mojoParameters.stream()
.map(mp -> XmlNode.newInstance(mp.name(), mp.value()))
.map(mp -> {
String value = mp.value();
if (!mp.xml()) {
// Treat as plain text - escape XML special characters
value = value.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;")
.replace("'", "&apos;");
}
String s = '<' + mp.name() + '>' + value + "</" + mp.name() + '>';
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a small details (not really important), but the code could be factorized a little bit:

String value = mp.value();
if (!mp.xml()) {
    // Treat as plain text - escape XML special characters
    value = value
            .replace("&", "&amp;")
            .replace("<", "&lt;")
            .replace(">", "&gt;")
            .replace("\"", "&quot;")
            .replace("'", "&apos;");
}
String s = '<' + mp.name() + '>' + value + "</" + mp.name() + '>';

I also replaced strings of 1 character by single characters.

return XmlService.read(new StringReader(s));
} catch (XMLStreamException e) {
throw new MavenException("Unable to parse xml: " + e + System.lineSeparator() + s, e);
}
})
.collect(Collectors.toList());
XmlNode config = XmlNode.newInstance("configuration", null, null, children, null);
pluginConfiguration = XmlService.merge(config, pluginConfiguration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,28 @@
* @return the parameter value
*/
String value();

/**
* Whether to parse the value as XML.
* When {@code true} (default), the value is parsed as XML content within the parameter element.
* When {@code false}, the value is treated as plain text (useful for comma-separated lists).
*
* <p>Example with XML parsing enabled (default):</p>
* <pre>
* {@code
* @MojoParameter(name = "items", value = "<item>one</item><item>two</item>")
* }
* </pre>
*
* <p>Example with XML parsing disabled:</p>
* <pre>
* {@code
* @MojoParameter(name = "items", value = "one,two,three", xml = false)
* }
* </pre>
*
* @return {@code true} to parse as XML, {@code false} to treat as plain text
* @since 4.0.0
*/
boolean xml() default true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.api.Project;
Expand Down Expand Up @@ -94,6 +96,129 @@ public void testParams(ExpressionEvaluatorMojo mojo) {
assertDoesNotThrow(mojo::execute);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@Basedir("${basedir}/target/test-classes")
@MojoParameter(name = "strings", value = "<string>value1</string><string>value2</string>")
public void testComplexParam(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.basedir);
assertNotNull(mojo.workdir);
assertEquals(List.of("value1", "value2"), mojo.strings);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@Basedir("${basedir}/target/test-classes")
@MojoParameter(name = "strings", value = "value1,value2", xml = false)
public void testCommaSeparatedParam(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.basedir);
assertNotNull(mojo.workdir);
assertEquals(List.of("value1", "value2"), mojo.strings);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "stringArray", value = "<string>item1</string><string>item2</string><string>item3</string>")
public void testStringArray(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.stringArray);
assertEquals(3, mojo.stringArray.length);
assertEquals("item1", mojo.stringArray[0]);
assertEquals("item2", mojo.stringArray[1]);
assertEquals("item3", mojo.stringArray[2]);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "mapParam", value = "<key1>value1</key1><key2>value2</key2>")
public void testMapParam(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.mapParam);
assertEquals(2, mojo.mapParam.size());
assertEquals("value1", mojo.mapParam.get("key1"));
assertEquals("value2", mojo.mapParam.get("key2"));
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(
name = "propertiesParam",
value = "<property><name>prop1</name><value>val1</value></property>"
+ "<property><name>prop2</name><value>val2</value></property>")
public void testPropertiesParam(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.propertiesParam);
assertEquals(2, mojo.propertiesParam.size());
assertEquals("val1", mojo.propertiesParam.getProperty("prop1"));
assertEquals("val2", mojo.propertiesParam.getProperty("prop2"));
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "beanParam", value = "<field1>fieldValue</field1><field2>42</field2>")
public void testBeanParam(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.beanParam);
assertEquals("fieldValue", mojo.beanParam.field1);
assertEquals(42, mojo.beanParam.field2);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "intValue", value = "123")
public void testIntValue(ExpressionEvaluatorMojo mojo) {
assertEquals(123, mojo.intValue);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "boolValue", value = "true")
public void testBoolValue(ExpressionEvaluatorMojo mojo) {
assertEquals(true, mojo.boolValue);
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "strings", value = "one,two,three,four", xml = false)
public void testCommaSeparatedListWithXmlFalse(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.strings);
assertEquals(4, mojo.strings.size());
assertEquals("one", mojo.strings.get(0));
assertEquals("two", mojo.strings.get(1));
assertEquals("three", mojo.strings.get(2));
assertEquals("four", mojo.strings.get(3));
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(
name = "strings",
value = "<string>alpha</string><string>beta</string><string>gamma</string>",
xml = true)
public void testListWithXmlTrue(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.strings);
assertEquals(3, mojo.strings.size());
assertEquals("alpha", mojo.strings.get(0));
assertEquals("beta", mojo.strings.get(1));
assertEquals("gamma", mojo.strings.get(2));
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "strings", value = "value-with-<special>&chars", xml = false)
public void testSpecialCharactersWithXmlFalse(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.strings);
assertEquals(1, mojo.strings.size());
assertEquals("value-with-<special>&chars", mojo.strings.get(0));
}

@Test
@InjectMojo(goal = COORDINATES, pom = CONFIG)
@MojoParameter(name = "stringArray", value = "a,b,c", xml = false)
public void testArrayWithCommaSeparated(ExpressionEvaluatorMojo mojo) {
assertNotNull(mojo.stringArray);
assertEquals(3, mojo.stringArray.length);
assertEquals("a", mojo.stringArray[0]);
assertEquals("b", mojo.stringArray[1]);
assertEquals("c", mojo.stringArray[2]);
}

@Mojo(name = "goal")
@Named("test:test-plugin:0.0.1-SNAPSHOT:goal") // this one is usually generated by maven-plugin-plugin
public static class ExpressionEvaluatorMojo implements org.apache.maven.api.plugin.Mojo {
Expand All @@ -105,6 +230,20 @@ public static class ExpressionEvaluatorMojo implements org.apache.maven.api.plug

private String param2;

private List<String> strings;

private String[] stringArray;

private Map<String, String> mapParam;

private Properties propertiesParam;

private TestBean beanParam;

private int intValue;

private boolean boolValue;

/** {@inheritDoc} */
@Override
public void execute() throws MojoException {
Expand All @@ -120,6 +259,30 @@ public void execute() throws MojoException {
}
}

/**
* A simple bean for testing complex parameter injection.
*/
public static class TestBean {
private String field1;
private int field2;

public String getField1() {
return field1;
}

public void setField1(String field1) {
this.field1 = field1;
}

public int getField2() {
return field2;
}

public void setField2(int field2) {
this.field2 = field2;
}
}

@Provides
@SuppressWarnings("unused")
Session session() {
Expand Down
28 changes: 28 additions & 0 deletions impl/maven-testing/src/test/resources/META-INF/maven/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,34 @@ under the License.
<name>param2</name>
<type>java.lang.String</type>
</parameter>
<parameter>
<name>strings</name>
<type>java.util.List</type>
</parameter>
<parameter>
<name>stringArray</name>
<type>[Ljava.lang.String;</type>
</parameter>
<parameter>
<name>mapParam</name>
<type>java.util.Map</type>
</parameter>
<parameter>
<name>propertiesParam</name>
<type>java.util.Properties</type>
</parameter>
<parameter>
<name>beanParam</name>
<type>org.apache.maven.api.plugin.testing.ExpressionEvaluatorTest$TestBean</type>
</parameter>
<parameter>
<name>intValue</name>
<type>int</type>
</parameter>
<parameter>
<name>boolValue</name>
<type>boolean</type>
</parameter>
<!--
<parameter>
<name>plain</name>
Expand Down