@@ -118,6 +118,8 @@ public class CacheConfigImpl implements org.apache.maven.buildcache.xml.CacheCon
118118 private final XmlService xmlService ;
119119 private final Provider <MavenSession > providerSession ;
120120 private final RuntimeInformation rtInfo ;
121+ private final PluginParameterLoader parameterLoader ;
122+ private final DefaultReconciliationLoader defaultReconciliationLoader ;
121123
122124 private volatile CacheState state ;
123125 private CacheConfig cacheConfig ;
@@ -129,6 +131,8 @@ public CacheConfigImpl(XmlService xmlService, Provider<MavenSession> providerSes
129131 this .xmlService = xmlService ;
130132 this .providerSession = providerSession ;
131133 this .rtInfo = rtInfo ;
134+ this .parameterLoader = new PluginParameterLoader ();
135+ this .defaultReconciliationLoader = new DefaultReconciliationLoader ();
132136 }
133137
134138 @ Nonnull
@@ -248,74 +252,190 @@ public boolean isLogAllProperties(MojoExecution mojoExecution) {
248252 }
249253
250254 private GoalReconciliation findReconciliationConfig (MojoExecution mojoExecution ) {
251- List <GoalReconciliation > reconciliation ;
255+ if (mojoExecution == null ) {
256+ return null ;
257+ }
252258
253- if ( cacheConfig . getExecutionControl () == null || cacheConfig . getExecutionControl (). getReconcile () == null ) {
254- // Use default reconciliation configs for common plugins
255- reconciliation = getDefaultReconciliationConfigs ();
256- } else {
257- reconciliation = cacheConfig . getExecutionControl (). getReconcile (). getPlugins () ;
259+ final String goal = mojoExecution . getGoal ();
260+ final Plugin plugin = mojoExecution . getPlugin ();
261+
262+ if ( plugin == null ) {
263+ return null ;
258264 }
259265
260- for (GoalReconciliation goalReconciliationConfig : reconciliation ) {
261- final String goal = mojoExecution .getGoal ();
266+ // First check explicit configuration
267+ if (cacheConfig .getExecutionControl () != null && cacheConfig .getExecutionControl ().getReconcile () != null ) {
268+ List <GoalReconciliation > explicitConfigs =
269+ cacheConfig .getExecutionControl ().getReconcile ().getPlugins ();
270+ for (GoalReconciliation config : explicitConfigs ) {
271+ if (isPluginMatch (plugin , config ) && Strings .CS .equals (goal , config .getGoal ())) {
272+ // Validate explicit config against parameter definitions (with version)
273+ validateReconciliationConfig (config , plugin );
274+ return config ;
275+ }
276+ }
277+ }
262278
263- if (isPluginMatch (mojoExecution .getPlugin (), goalReconciliationConfig )
264- && Strings .CS .equals (goal , goalReconciliationConfig .getGoal ())) {
265- return goalReconciliationConfig ;
279+ // Fall back to defaults if no explicit configuration found
280+ List <GoalReconciliation > defaults = getDefaultReconciliationConfigs ();
281+ for (GoalReconciliation config : defaults ) {
282+ if (isPluginMatch (plugin , config ) && Strings .CS .equals (goal , config .getGoal ())) {
283+ // Validate default config against parameter definitions (with version)
284+ validateReconciliationConfig (config , plugin );
285+ return config ;
266286 }
267287 }
288+
268289 return null ;
269290 }
270291
271- private List <GoalReconciliation > getDefaultReconciliationConfigs () {
272- List <GoalReconciliation > defaults = new ArrayList <>();
273-
274- // maven-compiler-plugin:compile - track source, target, release
275- GoalReconciliation compilerCompile = new GoalReconciliation ();
276- compilerCompile .setArtifactId ("maven-compiler-plugin" );
277- compilerCompile .setGoal ("compile" );
278-
279- TrackedProperty source = new TrackedProperty ();
280- source .setPropertyName ("source" );
281- compilerCompile .addReconcile (source );
282-
283- TrackedProperty target = new TrackedProperty ();
284- target .setPropertyName ("target" );
285- compilerCompile .addReconcile (target );
292+ /**
293+ * Validates a single reconciliation config against plugin parameter definitions.
294+ * Uses plugin version to load the appropriate parameter definition.
295+ */
296+ private void validateReconciliationConfig (GoalReconciliation config , Plugin plugin ) {
297+ String artifactId = config .getArtifactId ();
298+ String goal = config .getGoal ();
299+ String pluginVersion = plugin .getVersion ();
300+
301+ // Load parameter definition for this plugin with version
302+ PluginParameterDefinition pluginDef = parameterLoader .load (artifactId , pluginVersion );
303+
304+ if (pluginDef == null ) {
305+ LOGGER .warn (
306+ "No parameter definition found for plugin {}:{} version {}. "
307+ + "Cannot validate reconciliation configuration. "
308+ + "Consider adding a parameter definition file to plugin-parameters/{}.xml" ,
309+ artifactId ,
310+ goal ,
311+ pluginVersion != null ? pluginVersion : "unknown" ,
312+ artifactId );
313+ return ;
314+ }
286315
287- TrackedProperty release = new TrackedProperty ();
288- release .setPropertyName ("release" );
289- compilerCompile .addReconcile (release );
316+ // Get goal definition
317+ PluginParameterDefinition .GoalParameterDefinition goalDef = pluginDef .getGoal (goal );
318+ if (goalDef == null ) {
319+ LOGGER .warn (
320+ "Goal '{}' not found in parameter definition for plugin {} version {}. "
321+ + "Cannot validate reconciliation configuration." ,
322+ goal ,
323+ artifactId ,
324+ pluginVersion != null ? pluginVersion : "unknown" );
325+ return ;
326+ }
290327
291- defaults .add (compilerCompile );
328+ // Validate each tracked property
329+ List <TrackedProperty > properties = config .getReconciles ();
330+ if (properties == null ) {
331+ return ;
332+ }
292333
293- // maven-compiler-plugin:testCompile - track source, target, release
294- GoalReconciliation compilerTestCompile = new GoalReconciliation ();
295- compilerTestCompile .setArtifactId ("maven-compiler-plugin" );
296- compilerTestCompile .setGoal ("testCompile" );
334+ for (TrackedProperty property : properties ) {
335+ String propertyName = property .getPropertyName ();
336+
337+ if (!goalDef .hasParameter (propertyName )) {
338+ LOGGER .error (
339+ "Unknown parameter '{}' in reconciliation config for {}:{} version {}. "
340+ + "This may indicate a plugin version mismatch or renamed parameter. "
341+ + "Consider updating parameter definition or removing from reconciliation." ,
342+ propertyName ,
343+ artifactId ,
344+ goal ,
345+ pluginVersion != null ? pluginVersion : "unknown" );
346+ } else {
347+ PluginParameterDefinition .ParameterDefinition paramDef = goalDef .getParameter (propertyName );
348+ if (paramDef .isBehavioral ()) {
349+ LOGGER .warn (
350+ "Parameter '{}' in reconciliation config for {}:{} is categorized as BEHAVIORAL. "
351+ + "Behavioral parameters affect how the build runs but not the output. "
352+ + "Consider removing if it doesn't actually affect build artifacts." ,
353+ propertyName ,
354+ artifactId ,
355+ goal );
356+ }
357+ }
358+ }
359+ }
297360
298- TrackedProperty testSource = new TrackedProperty ();
299- testSource .setPropertyName ("source" );
300- compilerTestCompile .addReconcile (testSource );
361+ /**
362+ * Load default reconciliation configurations from XML.
363+ * Defaults are loaded from classpath: default-reconciliation/defaults.xml
364+ */
365+ private List <GoalReconciliation > getDefaultReconciliationConfigs () {
366+ List <GoalReconciliation > defaults = defaultReconciliationLoader .loadDefaults ();
301367
302- TrackedProperty testTarget = new TrackedProperty ();
303- testTarget .setPropertyName ("target" );
304- compilerTestCompile .addReconcile (testTarget );
368+ // Validate all default configurations against parameter definitions
369+ validateReconciliationConfigs (defaults );
305370
306- TrackedProperty testRelease = new TrackedProperty ();
307- testRelease .setPropertyName ("release" );
308- compilerTestCompile .addReconcile (testRelease );
371+ return defaults ;
372+ }
309373
310- defaults .add (compilerTestCompile );
374+ /**
375+ * Validates reconciliation configs against plugin parameter definitions.
376+ * Warns about unknown parameters that may indicate plugin changes or configuration errors.
377+ */
378+ private void validateReconciliationConfigs (List <GoalReconciliation > configs ) {
379+ for (GoalReconciliation config : configs ) {
380+ String artifactId = config .getArtifactId ();
381+ String goal = config .getGoal ();
382+
383+ // Load parameter definition for this plugin
384+ PluginParameterDefinition pluginDef = parameterLoader .load (artifactId );
385+
386+ if (pluginDef == null ) {
387+ LOGGER .warn (
388+ "No parameter definition found for plugin {}:{}. "
389+ + "Cannot validate reconciliation configuration. "
390+ + "Consider adding a parameter definition file to plugin-parameters/{}.xml" ,
391+ artifactId ,
392+ goal ,
393+ artifactId );
394+ continue ;
395+ }
311396
312- // maven-install-plugin:install - always run (empty reconciliation means it's tracked)
313- GoalReconciliation install = new GoalReconciliation ();
314- install .setArtifactId ("maven-install-plugin" );
315- install .setGoal ("install" );
316- defaults .add (install );
397+ // Get goal definition
398+ PluginParameterDefinition .GoalParameterDefinition goalDef = pluginDef .getGoal (goal );
399+ if (goalDef == null ) {
400+ LOGGER .warn (
401+ "Goal '{}' not found in parameter definition for plugin {}. "
402+ + "Cannot validate reconciliation configuration." ,
403+ goal ,
404+ artifactId );
405+ continue ;
406+ }
317407
318- return defaults ;
408+ // Validate each tracked property
409+ List <TrackedProperty > properties = config .getReconciles ();
410+ if (properties != null ) {
411+ for (TrackedProperty property : properties ) {
412+ String propertyName = property .getPropertyName ();
413+
414+ if (!goalDef .hasParameter (propertyName )) {
415+ LOGGER .error (
416+ "Unknown parameter '{}' in default reconciliation config for {}:{}. "
417+ + "This parameter is not defined in the plugin parameter definition. "
418+ + "This may indicate a plugin version mismatch or renamed parameter. "
419+ + "Please update the parameter definition or remove this property from reconciliation." ,
420+ propertyName ,
421+ artifactId ,
422+ goal );
423+ } else {
424+ PluginParameterDefinition .ParameterDefinition paramDef =
425+ goalDef .getParameter (propertyName );
426+ if (paramDef .isBehavioral ()) {
427+ LOGGER .warn (
428+ "Parameter '{}' in reconciliation config for {}:{} is categorized as BEHAVIORAL. "
429+ + "Behavioral parameters typically should not affect cache invalidation. "
430+ + "Consider removing this parameter from reconciliation if it doesn't affect build output." ,
431+ propertyName ,
432+ artifactId ,
433+ goal );
434+ }
435+ }
436+ }
437+ }
438+ }
319439 }
320440
321441 @ Nonnull
0 commit comments