Skip to content

Commit 9d307f0

Browse files
gnodetPankraz76
andauthored
[MNG-8746] Preserve property insertion order in WrapperProperties (#2404)
* Fix MNG-8746: Preserve property insertion order in WrapperProperties This commit implements order preservation for properties in the Maven compat layer's WrapperProperties class, ensuring that properties maintain their insertion order when accessed through the Properties API. Key changes: 1. Enhanced WrapperProperties template (src/mdo/java/WrapperProperties.java): - Added internal OrderedProperties class that maintains insertion order - Implemented caching mechanism to preserve order across read/write operations - Modified all read operations to use the ordered cache - Simplified write operations to work directly with the ordered properties 2. OrderedProperties implementation: - Uses ArrayList to track key insertion order - Overrides put/setProperty/remove to maintain order - Custom KeySet and EntrySet implementations that iterate in insertion order - Removed unnecessary synchronized wrappers that interfered with ordering 3. Updated model-v3.vm template: - Ensured LinkedHashMap is used when converting properties to v4 API - This preserves order when properties are synced between compat and v4 layers 4. Added comprehensive tests: - PropertiesOrderTest: Tests v4 API model order preservation - WrapperPropertiesOrderTest: Tests compat layer order preservation - Covers various scenarios including modification and initial properties The implementation ensures that properties accessed through model.getProperties() maintain their insertion order, which is important for consistent behavior and reproducible builds. Fixes: MNG-8746 * Update src/mdo/java/WrapperProperties.java Co-authored-by: Pankraz76 <[email protected]> * Update src/mdo/java/WrapperProperties.java Co-authored-by: Pankraz76 <[email protected]> --------- Co-authored-by: Pankraz76 <[email protected]>
1 parent 6fac2e5 commit 9d307f0

File tree

4 files changed

+352
-73
lines changed

4 files changed

+352
-73
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.model;
20+
21+
import java.util.ArrayList;
22+
import java.util.LinkedHashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Properties;
26+
27+
import org.junit.jupiter.api.Test;
28+
29+
import static org.junit.jupiter.api.Assertions.assertEquals;
30+
import static org.junit.jupiter.api.Assertions.assertNotNull;
31+
32+
/**
33+
* Test for MNG-8746: Properties order is preserved in model
34+
*/
35+
public class PropertiesOrderTest {
36+
37+
@Test
38+
public void testPropertiesOrderPreservedInImmutableModel() {
39+
// Create properties with specific insertion order using LinkedHashMap
40+
Map<String, String> orderedMap = new LinkedHashMap<>();
41+
orderedMap.put("third", "3");
42+
orderedMap.put("first", "1");
43+
orderedMap.put("second", "2");
44+
45+
// Create model and set properties
46+
Model model = new Model();
47+
Properties props = model.getProperties();
48+
49+
// Create properties and populate from map to maintain order
50+
orderedMap.forEach(props::setProperty);
51+
52+
// Get the immutable delegate (v4 API model is already immutable)
53+
org.apache.maven.api.model.Model immutable = model.getDelegate();
54+
55+
// Verify order is preserved
56+
Map<String, String> resultProps = immutable.getProperties();
57+
assertNotNull(resultProps);
58+
59+
// Check order by collecting keys in iteration order
60+
List<String> keys = new ArrayList<>(resultProps.keySet());
61+
62+
// Verify the original insertion order is maintained
63+
assertEquals(3, keys.size());
64+
assertEquals("third", keys.get(0));
65+
assertEquals("first", keys.get(1));
66+
assertEquals("second", keys.get(2));
67+
}
68+
69+
@Test
70+
public void testPropertiesOrderPreservedInMutableModel() {
71+
// Create ordered map to simulate properties with specific order
72+
Map<String, String> orderedMap = new LinkedHashMap<>();
73+
orderedMap.put("z-property", "z");
74+
orderedMap.put("a-property", "a");
75+
orderedMap.put("m-property", "m");
76+
77+
// Create and populate model
78+
Model model = new Model();
79+
Properties props = model.getProperties();
80+
81+
// Create properties and populate from map to maintain order
82+
orderedMap.forEach(props::setProperty);
83+
84+
// Get properties back and verify order
85+
Properties resultProps = model.getProperties();
86+
87+
// Check order by collecting keys in iteration order
88+
List<String> keys = new ArrayList<>();
89+
resultProps.keySet().forEach(k -> keys.add(k.toString()));
90+
91+
// Verify the original insertion order is maintained
92+
assertEquals(3, keys.size());
93+
assertEquals("z-property", keys.get(0));
94+
assertEquals("a-property", keys.get(1));
95+
assertEquals("m-property", keys.get(2));
96+
}
97+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.model;
20+
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import java.util.Properties;
24+
25+
import org.junit.jupiter.api.Test;
26+
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
29+
/**
30+
* Test for order preservation in WrapperProperties used by Model
31+
*/
32+
public class WrapperPropertiesOrderTest {
33+
34+
@Test
35+
public void testOrderPreservationAfterModification() {
36+
// Create a model with properties
37+
Model model = new Model();
38+
Properties modelProps = model.getProperties();
39+
40+
// Add properties in specific order
41+
modelProps.setProperty("first", "1");
42+
modelProps.setProperty("second", "2");
43+
44+
// Modify existing property
45+
modelProps.setProperty("first", "modified");
46+
47+
// Add new property
48+
modelProps.setProperty("third", "3");
49+
50+
// Collect keys in iteration order
51+
List<String> keys = new ArrayList<>();
52+
modelProps.keySet().forEach(k -> keys.add(k.toString()));
53+
54+
// Verify order is preserved (first should still be first since it was modified, not re-added)
55+
assertEquals(3, keys.size());
56+
assertEquals("first", keys.get(0));
57+
assertEquals("second", keys.get(1));
58+
assertEquals("third", keys.get(2));
59+
60+
// Verify value was updated
61+
assertEquals("modified", modelProps.getProperty("first"));
62+
}
63+
}

0 commit comments

Comments
 (0)