Bump org.easymock:easymock from 4.0.2 to 5.1.0 #352, #355, #375.
diff --git a/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java b/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java
new file mode 100644
index 000000000..34e21ab91
--- /dev/null
+++ b/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4.properties;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * A drop-in replacement for {@link Properties} for ordered keys.
+ *
+ * Overrides methods to keep keys in insertion order. Allows other methods in the superclass to work with ordered keys.
+ *
+ *
+ * @see OrderedPropertiesFactory#INSTANCE
+ * @since 4.5
+ */
+public class OrderedProperties extends Properties {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Preserves the insertion order.
+ */
+ private final LinkedHashSet orderedKeys = new LinkedHashSet<>();
+
+ @Override
+ public synchronized void clear() {
+ orderedKeys.clear();
+ super.clear();
+ }
+
+ @Override
+ public synchronized Object compute(Object key, BiFunction super Object, ? super Object, ? extends Object> remappingFunction) {
+ Object compute = super.compute(key, remappingFunction);
+ if (compute != null) {
+ orderedKeys.add(key);
+ }
+ return compute;
+ }
+
+ @Override
+ public synchronized Object computeIfAbsent(Object key, Function super Object, ? extends Object> mappingFunction) {
+ Object computeIfAbsent = super.computeIfAbsent(key, mappingFunction);
+ if (computeIfAbsent != null) {
+ orderedKeys.add(key);
+ }
+ return computeIfAbsent;
+ }
+
+ @Override
+ public synchronized Enumeration keys() {
+ return Collections.enumeration(orderedKeys);
+ }
+
+ @Override
+ public Set keySet() {
+ return orderedKeys;
+ }
+
+ @Override
+ public synchronized Object merge(final Object key, final Object value,
+ final BiFunction super Object, ? super Object, ? extends Object> remappingFunction) {
+ orderedKeys.add(key);
+ return super.merge(key, value, remappingFunction);
+ }
+
+ @Override
+ public Enumeration> propertyNames() {
+ return Collections.enumeration(orderedKeys);
+ }
+
+ @Override
+ public synchronized Object put(final Object key, final Object value) {
+ Object put = super.put(key, value);
+ if (put == null) {
+ orderedKeys.add(key);
+ }
+ return put;
+ }
+
+ @Override
+ public synchronized void putAll(final Map extends Object, ? extends Object> t) {
+ orderedKeys.addAll(t.keySet());
+ super.putAll(t);
+ }
+
+ @Override
+ public synchronized Object putIfAbsent(final Object key, final Object value) {
+ Object putIfAbsent = super.putIfAbsent(key, value);
+ if (putIfAbsent == null) {
+ orderedKeys.add(key);
+ }
+ return putIfAbsent;
+ }
+
+ @Override
+ public synchronized Object remove(final Object key) {
+ Object remove = super.remove(key);
+ if (remove != null) {
+ orderedKeys.remove(key);
+ }
+ return remove;
+ }
+
+ @Override
+ public synchronized boolean remove(final Object key, final Object value) {
+ boolean remove = super.remove(key, value);
+ if (remove) {
+ orderedKeys.remove(key);
+ }
+ return remove;
+ }
+}
diff --git a/src/main/java/org/apache/commons/collections4/properties/OrderedPropertiesFactory.java b/src/main/java/org/apache/commons/collections4/properties/OrderedPropertiesFactory.java
new file mode 100644
index 000000000..e2039fcad
--- /dev/null
+++ b/src/main/java/org/apache/commons/collections4/properties/OrderedPropertiesFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections4.properties;
+
+/**
+ * Creates and loads {@link OrderedProperties}.
+ *
+ * @see OrderedProperties
+ * @since 4.5
+ */
+public class OrderedPropertiesFactory extends AbstractPropertiesFactory {
+
+ /**
+ * The singleton instance.
+ */
+ public static final OrderedPropertiesFactory INSTANCE = new OrderedPropertiesFactory();
+
+ /**
+ * Constructs an instance.
+ */
+ private OrderedPropertiesFactory() {
+ // There is only one instance.
+ }
+
+ /**
+ * Subclasses override to provide customized properties instances.
+ *
+ * @return a new Properties instance.
+ */
+ @Override
+ protected OrderedProperties createProperties() {
+ return new OrderedProperties();
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java b/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java
index f4daf39ba..ac7d1f3cf 100644
--- a/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java
+++ b/src/test/java/org/apache/commons/collections4/properties/AbstractPropertiesFactoryTest.java
@@ -64,14 +64,14 @@ public abstract class AbstractPropertiesFactoryTest {
assertEquals("value11", properties.getProperty("key11"));
}
- private boolean isXmlTest(final String fileExtension) {
- return ".xml".equals(fileExtension);
- }
-
private String getPathString(final String fileExtension) {
return BulkTest.TEST_PROPERTIES_PATH + "test" + fileExtension;
}
+ private boolean isXmlTest(final String fileExtension) {
+ return ".xml".equals(fileExtension);
+ }
+
@Test
public void testInstance() {
assertNotNull(PropertiesFactory.INSTANCE);
diff --git a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesFactoryTest.java b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesFactoryTest.java
new file mode 100644
index 000000000..7384a6f5e
--- /dev/null
+++ b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesFactoryTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4.properties;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link OrderedPropertiesFactory}.
+ */
+public class OrderedPropertiesFactoryTest extends AbstractPropertiesFactoryTest {
+
+ public OrderedPropertiesFactoryTest() {
+ super(OrderedPropertiesFactory.INSTANCE);
+ }
+
+ @Test
+ @Override
+ public void testInstance() {
+ assertNotNull(OrderedPropertiesFactory.INSTANCE);
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java
new file mode 100644
index 000000000..0974a617d
--- /dev/null
+++ b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4.properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link OrderedProperties}.
+ */
+public class OrderedPropertiesTest {
+
+ private void assertAscendingOrder(final OrderedProperties orderedProperties) {
+ final int first = 1;
+ final int last = 11;
+ final Enumeration enumObjects = orderedProperties.keys();
+ for (int i = first; i <= last; i++) {
+ assertEquals("key" + i, enumObjects.nextElement());
+ }
+ final Iterator iterSet = orderedProperties.keySet().iterator();
+ for (int i = first; i <= last; i++) {
+ assertEquals("key" + i, iterSet.next());
+ }
+ final Enumeration> propertyNames = orderedProperties.propertyNames();
+ for (int i = first; i <= last; i++) {
+ assertEquals("key" + i, propertyNames.nextElement());
+ }
+ }
+
+ private OrderedProperties assertDescendingOrder(final OrderedProperties orderedProperties) {
+ final int first = 11;
+ final int last = 1;
+ final Enumeration enumObjects = orderedProperties.keys();
+ for (int i = first; i <= last; i--) {
+ assertEquals("key" + i, enumObjects.nextElement());
+ }
+ final Iterator iterSet = orderedProperties.keySet().iterator();
+ for (int i = first; i <= last; i--) {
+ assertEquals("key" + i, iterSet.next());
+ }
+ final Enumeration> propertyNames = orderedProperties.propertyNames();
+ for (int i = first; i <= last; i--) {
+ assertEquals("key" + i, propertyNames.nextElement());
+ }
+ return orderedProperties;
+ }
+
+ private OrderedProperties loadOrderedKeysReverse() throws FileNotFoundException, IOException {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ try (FileReader reader = new FileReader("src/test/resources/org/apache/commons/collections4/properties/test-reverse.properties")) {
+ orderedProperties.load(reader);
+ }
+ return assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testCompute() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ final AtomicInteger aInt = new AtomicInteger(i);
+ orderedProperties.compute("key" + i, (k, v) -> "value" + aInt.get());
+ }
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ final AtomicInteger aInt = new AtomicInteger(i);
+ orderedProperties.compute("key" + i, (k, v) -> "value" + aInt.get());
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testComputeIfAbsent() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ final AtomicInteger aInt = new AtomicInteger(i);
+ orderedProperties.computeIfAbsent("key" + i, k -> "value" + aInt.get());
+ }
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ final AtomicInteger aInt = new AtomicInteger(i);
+ orderedProperties.computeIfAbsent("key" + i, k -> "value" + aInt.get());
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testEntrySet() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ for (char ch = 'Z'; ch >= 'A'; ch--) {
+ orderedProperties.put(String.valueOf(ch), "Value" + ch);
+ }
+ final Iterator> entries = orderedProperties.entrySet().iterator();
+ for (char ch = 'Z'; ch <= 'A'; ch++) {
+ final Map.Entry entry = entries.next();
+ assertEquals(String.valueOf(ch), entry.getKey());
+ assertEquals("Value" + ch, entry.getValue());
+ }
+ }
+
+ @Test
+ public void testKeys() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ for (char ch = 'Z'; ch >= 'A'; ch--) {
+ orderedProperties.put(String.valueOf(ch), "Value" + ch);
+ }
+ final Enumeration keys = orderedProperties.keys();
+ for (char ch = 'Z'; ch <= 'A'; ch++) {
+ assertEquals(String.valueOf(ch), keys.nextElement());
+ }
+ }
+
+ @Test
+ public void testLoadOrderedKeys() throws FileNotFoundException, IOException {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ try (FileReader reader = new FileReader("src/test/resources/org/apache/commons/collections4/properties/test.properties")) {
+ orderedProperties.load(reader);
+ }
+ assertAscendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testLoadOrderedKeysReverse() throws FileNotFoundException, IOException {
+ loadOrderedKeysReverse();
+ }
+
+ @Test
+ public void testMerge() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ orderedProperties.merge("key" + i, "value" + i, (k, v) -> v);
+ }
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ orderedProperties.merge("key" + i, "value" + i, (k, v) -> v);
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testPut() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ orderedProperties.put("key" + i, "value" + i);
+ }
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ orderedProperties.put("key" + i, "value" + i);
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testPutAll() {
+ final OrderedProperties sourceProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ sourceProperties.put("key" + i, "value" + i);
+ }
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ orderedProperties.putAll(sourceProperties);
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ orderedProperties.put("key" + i, "value" + i);
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testPutIfAbsent() {
+ final OrderedProperties orderedProperties = new OrderedProperties();
+ int first = 1;
+ int last = 11;
+ for (int i = first; i <= last; i++) {
+ orderedProperties.putIfAbsent("key" + i, "value" + i);
+ }
+ assertAscendingOrder(orderedProperties);
+ orderedProperties.clear();
+ first = 11;
+ last = 1;
+ for (int i = first; i >= last; i--) {
+ orderedProperties.putIfAbsent("key" + i, "value" + i);
+ }
+ assertDescendingOrder(orderedProperties);
+ }
+
+ @Test
+ public void testRemoveKey() throws FileNotFoundException, IOException {
+ final OrderedProperties props = loadOrderedKeysReverse();
+ final String k = "key1";
+ props.remove(k);
+ assertFalse(props.contains(k));
+ assertFalse(props.containsKey(k));
+ assertFalse(Collections.list(props.keys()).contains(k));
+ assertFalse(Collections.list(props.propertyNames()).contains(k));
+ }
+
+ @Test
+ public void testRemoveKeyValue() throws FileNotFoundException, IOException {
+ final OrderedProperties props = loadOrderedKeysReverse();
+ final String k = "key1";
+ props.remove(k, "value1");
+ assertFalse(props.contains(k));
+ assertFalse(props.containsKey(k));
+ assertFalse(Collections.list(props.keys()).contains(k));
+ assertFalse(Collections.list(props.propertyNames()).contains(k));
+ }
+}
diff --git a/src/test/resources/org/apache/commons/collections4/properties/test-reverse.properties b/src/test/resources/org/apache/commons/collections4/properties/test-reverse.properties
new file mode 100644
index 000000000..9734ebb06
--- /dev/null
+++ b/src/test/resources/org/apache/commons/collections4/properties/test-reverse.properties
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+key11 = value11
+key10 = value10
+key9 = value9
+key8 = value8
+key7 = value7
+key6 = value6
+key5 = value5
+key4 = value4
+key3 = value3
+key2 = value2
+key1 = value1