Apache Software Foundation / Maven Core
Merged upstreamCorrectnessMerged Aug 30, 2026

Preserve Properties defaults in immutable copies

Fixed Maven's read-only `Properties` implementation so inherited and recursive defaults remain visible through `getProperty()` after an immutable copy is created.

apache/maven · #12910

Maven 4 compatibility fix

Immutable `Properties` copies now retain inherited defaults while preserving the direct-map semantics expected by existing callers.

Problem

`ROProperties` copied only direct map entries from the source. Values inherited through the defaults chain disappeared, causing standard `Properties` lookups to return `null` and changing behavior for consumers that relied on recursive defaults or string fallback behind direct non-string values.

Approach

Snapshotted the effective inherited string properties into a private defaults object before copying direct entries. The implementation keeps inherited values outside the direct map, preserves overrides and non-string entries, avoids retaining a mutable source-default reference, and skips the extra allocation when no inherited defaults exist.

Impact and scope

  • Restores standard `Properties.getProperty()` behavior for immutable Maven configuration snapshots.
  • Keeps `containsKey()`, size, and iteration limited to direct entries while preserving recursive fallback semantics.
  • Aligns the public API implementation, internal XML implementation, and generated MDO template so maintained copies cannot drift.

Validation

  • Added regression coverage for direct and inherited values, recursive defaults, overrides, non-string entries, map membership, and mutation isolation.
  • Passed focused `ImmutableCollectionsTest` verification and the complete `mvn clean verify` build.
  • All three landed commits and the final merge commit are GitHub-verified; the change received maintainer approval.