[MNG-8765] Pre-interpolate plugin configuration before type conversion - #12686
[MNG-8765] Pre-interpolate plugin configuration before type conversion#12686gnodet wants to merge 1 commit into
Conversation
gnodet
left a comment
There was a problem hiding this comment.
The pre-interpolation approach is sound in principle, but the implementation has a fundamental issue that renders the fix ineffective:
1. Interpolated values are silently discarded (high severity)
interpolateConfiguration stores resolved values in child XmlPlexusConfiguration wrappers obtained via getChildren(), but both the Plexus ObjectWithFieldsConverter and Maven's EnhancedConfigurationConverter access children via getChild(int), which creates new wrappers from the parent's unmodified immutable XmlNode tree — all interpolated values are lost.
Trace:
getChildren()populates achildrenCachewith wrapperssetValue()replaces the wrapper's internalxmlNodebut does NOT update the parent'sxmlNode.children()(XmlNode is immutable)getChild(int)does NOT use the cache — it creates a fresh wrapper fromxmlNode.children().get(i), which still holds the original uninterpolated child
Suggested approach: Reconstruct the XmlNode tree bottom-up with interpolated values and wrap it in a fresh XmlPlexusConfiguration, rather than mutating transient wrapper objects.
2. Tests don't cover the actual failure scenario (high severity)
The tests use POM-defined properties (test.version=1.2.3) and CLI properties (-Dcli.version=2.0.0), both of which are already resolved during model interpolation — before interpolateConfiguration runs. The tests pass with or without the fix. The actual MNG-8765 scenario (properties set dynamically at runtime via project.properties.setProperty() by Groovy/GMaven scripts) is not tested.
3. Fix only in loadV3Mojo (medium severity)
The interpolateConfiguration call is only added to loadV3Mojo. loadV4Mojo has the same pomConfiguration → populateMojoExecutionFields flow but no pre-interpolation, leaving V4 mojos with URI-typed parameters unprotected.
4. Javadoc inaccuracy (low severity)
The Javadoc says @return a new PlexusConfiguration but the method returns the same object mutated in place.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
gnodet
left a comment
There was a problem hiding this comment.
Review: [MNG-8765] Pre-interpolate plugin configuration before type conversion
The intent of this fix is sound — runtime properties set by scripts (e.g., Groovy calling project.properties.setProperty(...)) need resolution before URI type converters parse the value. However, the implementation has a structural issue that makes it ineffective.
Confirmed findings:
-
[high] Pre-interpolation has no effect on type converters —
interpolateConfigurationmodifies child wrappers obtained viagetChildren(), but theComponentConfigurator(both standard plexusObjectWithFieldsConverterand Maven'sEnhancedConfigurationConverter) accesses children viagetChild(int i), which creates new wrappers from the parent's unchanged immutableXmlNode. SinceXmlNodeis@Immutable,setValue()on a child wrapper replaces only that wrapper'sxmlNodereference — the parent'sxmlNode.children()list is never updated. The interpolated values are invisible to type converters.A possible fix: build a new
XmlNodetree with interpolated values (usingXmlNode.newBuilder()recursively) and wrap the result in a freshXmlPlexusConfiguration, or fixXmlPlexusConfiguration.getChild(int i)to consult thechildrenCachewhen populated. -
[medium] Missing from
loadV4Mojo— The pre-interpolation is only added toloadV3Mojobut not toloadV4Mojo(line 598), which has the identical structure. If V4 mojos use URI-typed parameters with runtime properties, they would have the same issue. -
[medium] Integration tests don't cover the actual scenario — Both test methods use properties that model interpolation already resolves:
${test.version}(POM property) and${cli.version}(system property from-D). By the timeloadV3Mojoruns, these values are already resolved in the DOM. The actual MNG-8765 scenario — a property set at runtime viaproject.properties.setProperty()by a prior plugin — is not covered. -
[low] Silent exception swallowing — Empty
catch (ExpressionEvaluationException e)blocks. Alogger.debug()call would aid troubleshooting.
This review was generated by an AI agent (Claude Code) and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
gnodet
left a comment
There was a problem hiding this comment.
The pre-interpolation approach is sound in principle, but the implementation has a structural issue that may render the fix ineffective:
High severity:
-
Interpolated values invisible to downstream type converters:
interpolateConfiguration()modifies child wrappers obtained viagetChildren(), which populateschildrenCache. However, the downstream Plexus configurators (BasicComponentConfiguratorandEnhancedConfigurationConverter) access children viagetChild(int i), which inXmlPlexusConfiguration(line 165-171) creates new wrappers directly fromxmlNode.children().get(i)— completely bypassingchildrenCache. SinceXmlNodeis immutable andsetValue()only replaces a wrapper's internalxmlNodereference (not the parent's child list), all interpolated values are invisible to type converters.Additionally, the existing expression evaluation path in
AbstractBasicConverter.fromExpression()already resolves${...}expressions viaPluginParameterExpressionEvaluatorbefore type conversion, andUriConverter.fromString()then converts the resolved string. This may make pre-interpolation redundant even if it worked. -
Tests don't cover the actual MNG-8765 scenario: Both test methods use properties already resolved during model interpolation —
${test.version}(POM<properties>) and${cli.version}(-DCLI). These values are fully resolved beforeloadV3Mojoruns, so the tests pass with or without theinterpolateConfigurationcall. The actual scenario (properties set dynamically at runtime viaproject.properties.setProperty()) is not tested.
Medium severity:
- V4 mojos unprotected:
interpolateConfigurationis only added toloadV3Mojo. TheloadV4Mojomethod has the identical flow but no pre-interpolation.
Low severity:
- Javadoc says "@return a new PlexusConfiguration" but the method mutates and returns the same object.
- Two
catch (ExpressionEvaluationException e)blocks silently swallow exceptions — consider addinglogger.debug()for troubleshooting.
Suggested approach: either reconstruct the XmlNode tree bottom-up with interpolated values using XmlNode.newBuilder(), or fix XmlPlexusConfiguration.getChild(int i) to consult childrenCache, or move interpolation to a point where values are consumed directly.
This review was generated by an AI agent (Claude Code) and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
5fd4f75 to
ca57b6f
Compare
Fix the property interpolation ordering issue for URI-typed plugin
parameters. The ComponentConfigurator converts raw strings to
java.net.URI BEFORE resolving ${...} properties, causing
URISyntaxException because curly braces are illegal URI characters.
The fix pre-interpolates the configuration tree by rebuilding the
immutable XmlNode hierarchy bottom-up with resolved values before
passing it to the ComponentConfigurator. This is necessary because
XmlNode is @immutable — mutating transient PlexusConfiguration
wrappers does not propagate changes back to the underlying tree.
Only expressions referencing properties that were NOT available during
model interpolation are resolved. Properties from the POM's
<properties>, user properties (-D), and system properties are skipped
because model interpolation already had a chance to resolve them — any
surviving ${...} for those properties was intentionally escaped
(MNG-3558).
Key changes:
- Add interpolateXmlNode() that rebuilds the XmlNode tree with
resolved expression values, preserving immutability semantics
- Only interpolate runtime-set properties (not model-time ones),
respecting property escaping (MNG-3558)
- Apply pre-interpolation to both loadV3Mojo and loadV4Mojo paths
- Add XmlPlexusConfiguration.toXmlNode() accessor
- Add SetPropertyMojo to IT plugin for runtime property testing
- Add integration test covering the actual MNG-8765 scenario:
properties set dynamically at runtime via
project.getProperties().setProperty() (not available during
model interpolation)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
ca57b6f to
e6d3e09
Compare
Summary
PlexusConfigurationvalues using the expression evaluator inDefaultMavenPluginManagerbefore passing them to theComponentConfigurator, ensuring${...}property references are fully resolved before type converters (likeUriConverter) process the valuesproject.properties.setProperty()) are not available during model interpolation and reach type converters unresolved, causingURISyntaxExceptionfor URI-typed parametersRegression found in CloudStack (gnodet/maven4-testing#34733) where a URI parameter with
${cs.version}set by a Groovy script at runtime causedURISyntaxException.Test plan
impl/maven-core)MavenITmng8765UriPropertyInterpolationTestpasses:-D) in URI parameters🤖 Generated with Claude Code