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.