diff --git a/RELEASE-NOTES.html b/RELEASE-NOTES.html
index 49f5046ee..d2c7f3112 100644
--- a/RELEASE-NOTES.html
+++ b/RELEASE-NOTES.html
@@ -86,6 +86,7 @@ If this causes major headaches to anyone please contact commons-dev at jakarta.a
AbstractMapBag.BagIterator.remove - Removing the last entry used to break the class invariants [35747]
BoundedFifoBuffer/CircularFifoBuffer - Fix serialization to work in case where buffer serialized when full [31433]
BoundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [33071]
+UnboundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [35733]
IteratorChain.remove() - Fix to avoid IllegalStateException when one of the underlying iterators is a FilterIterator [34267]
ExtendedProperties.convertProperties() - Fix to handle default properties maps correctly [32204]
Add casts to avoid some JDK1.5 compilation warnings [35474]
diff --git a/project.xml b/project.xml
index 466230b84..938f3d0d0 100644
--- a/project.xml
+++ b/project.xml
@@ -300,6 +300,9 @@
Jon Schewe
+
+ Andreas Schlosser
+
Christian Siefkes
diff --git a/src/java/org/apache/commons/collections/UnboundedFifoBuffer.java b/src/java/org/apache/commons/collections/UnboundedFifoBuffer.java
index cd2358524..8ffab4d24 100644
--- a/src/java/org/apache/commons/collections/UnboundedFifoBuffer.java
+++ b/src/java/org/apache/commons/collections/UnboundedFifoBuffer.java
@@ -49,6 +49,7 @@ import java.util.NoSuchElementException;
* @author Berin Loritsch
* @author Paul Jack
* @author Stephen Colebourne
+ * @author Andreas Schlosser
*/
public class UnboundedFifoBuffer extends AbstractCollection implements Buffer {
@@ -254,15 +255,10 @@ public class UnboundedFifoBuffer extends AbstractCollection implements Buffer {
}
// Other elements require us to shift the subsequent elements
- int i = lastReturnedIndex + 1;
+ int i = increment(lastReturnedIndex);
while (i != m_tail) {
- if (i >= m_buffer.length) {
- m_buffer[i - 1] = m_buffer[0];
- i = 0;
- } else {
- m_buffer[i - 1] = m_buffer[i];
- i++;
- }
+ m_buffer[decrement(i)] = m_buffer[i];
+ i = increment(i);
}
lastReturnedIndex = -1;
diff --git a/src/java/org/apache/commons/collections/buffer/UnboundedFifoBuffer.java b/src/java/org/apache/commons/collections/buffer/UnboundedFifoBuffer.java
index 9dbd8021e..53cffdc5f 100644
--- a/src/java/org/apache/commons/collections/buffer/UnboundedFifoBuffer.java
+++ b/src/java/org/apache/commons/collections/buffer/UnboundedFifoBuffer.java
@@ -294,15 +294,10 @@ public class UnboundedFifoBuffer extends AbstractCollection implements Buffer, S
}
// Other elements require us to shift the subsequent elements
- int i = lastReturnedIndex + 1;
+ int i = increment(lastReturnedIndex);
while (i != tail) {
- if (i >= buffer.length) {
- buffer[i - 1] = buffer[0];
- i = 0;
- } else {
- buffer[i - 1] = buffer[i];
- i++;
- }
+ buffer[decrement(i)] = buffer[i];
+ i = increment(i);
}
lastReturnedIndex = -1;
diff --git a/src/test/org/apache/commons/collections/TestUnboundedFifoBuffer.java b/src/test/org/apache/commons/collections/TestUnboundedFifoBuffer.java
index b93a99efb..6462566c0 100644
--- a/src/test/org/apache/commons/collections/TestUnboundedFifoBuffer.java
+++ b/src/test/org/apache/commons/collections/TestUnboundedFifoBuffer.java
@@ -142,5 +142,272 @@ public class TestUnboundedFifoBuffer extends AbstractTestCollection {
}
fail();
}
-}
+ //-----------------------------------------------------------------------
+ public void testInternalStateAdd() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(2);
+ assertEquals(3, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(0, test.m_tail);
+ test.add("A");
+ assertEquals(3, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(1, test.m_tail);
+ test.add("B");
+ assertEquals(3, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(2, test.m_tail);
+ test.add("C"); // forces m_buffer increase
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+ test.add("D");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(4, test.m_tail);
+ }
+
+ public void testInternalStateAddWithWrap() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(0, test.m_tail);
+ test.add("A");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(1, test.m_tail);
+ test.add("B");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(2, test.m_tail);
+ test.add("C");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+ test.remove("A");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(3, test.m_tail);
+ test.remove("B");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(3, test.m_tail);
+ test.add("D");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(0, test.m_tail);
+ test.add("E");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(1, test.m_tail);
+ }
+
+ public void testInternalStateRemove1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+
+ test.remove("A");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(3, test.m_tail);
+
+ test.add("D");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(4, test.m_tail);
+ }
+
+ public void testInternalStateRemove2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+
+ test.remove("B");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(2, test.m_tail);
+
+ test.add("D");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemove1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+
+ Iterator it = test.iterator();
+ it.next();
+ it.remove();
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(3, test.m_tail);
+
+ test.add("D");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(4, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemove2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+
+ Iterator it = test.iterator();
+ it.next();
+ it.next();
+ it.remove();
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(2, test.m_tail);
+
+ test.add("D");
+ assertEquals(5, test.m_buffer.length);
+ assertEquals(0, test.m_head);
+ assertEquals(3, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(0, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(0, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(0, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ assertEquals("C", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(3, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd3() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(0, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(1, test.m_head);
+ assertEquals(3, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(1, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(3, test.m_head);
+ assertEquals(1, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(1, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(0, test.m_tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap3() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(1, test.m_tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ assertEquals("E", it.next());
+ it.remove();
+ assertEquals(4, test.m_buffer.length);
+ assertEquals(2, test.m_head);
+ assertEquals(0, test.m_tail);
+ }
+
+}
diff --git a/src/test/org/apache/commons/collections/buffer/TestUnboundedFifoBuffer.java b/src/test/org/apache/commons/collections/buffer/TestUnboundedFifoBuffer.java
index e6b9b2ed8..c6207218a 100644
--- a/src/test/org/apache/commons/collections/buffer/TestUnboundedFifoBuffer.java
+++ b/src/test/org/apache/commons/collections/buffer/TestUnboundedFifoBuffer.java
@@ -144,6 +144,274 @@ public class TestUnboundedFifoBuffer extends AbstractTestCollection {
fail();
}
+ //-----------------------------------------------------------------------
+ public void testInternalStateAdd() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(2);
+ assertEquals(3, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(0, test.tail);
+ test.add("A");
+ assertEquals(3, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(1, test.tail);
+ test.add("B");
+ assertEquals(3, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(2, test.tail);
+ test.add("C"); // forces buffer increase
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+ test.add("D");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(4, test.tail);
+ }
+
+ public void testInternalStateAddWithWrap() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ assertEquals(4, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(0, test.tail);
+ test.add("A");
+ assertEquals(4, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(1, test.tail);
+ test.add("B");
+ assertEquals(4, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(2, test.tail);
+ test.add("C");
+ assertEquals(4, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+ test.remove("A");
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(3, test.tail);
+ test.remove("B");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(3, test.tail);
+ test.add("D");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(0, test.tail);
+ test.add("E");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(1, test.tail);
+ }
+
+ public void testInternalStateRemove1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+
+ test.remove("A");
+ assertEquals(5, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(3, test.tail);
+
+ test.add("D");
+ assertEquals(5, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(4, test.tail);
+ }
+
+ public void testInternalStateRemove2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+
+ test.remove("B");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(2, test.tail);
+
+ test.add("D");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+ }
+
+ public void testInternalStateIteratorRemove1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+
+ Iterator it = test.iterator();
+ it.next();
+ it.remove();
+ assertEquals(5, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(3, test.tail);
+
+ test.add("D");
+ assertEquals(5, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(4, test.tail);
+ }
+
+ public void testInternalStateIteratorRemove2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+
+ Iterator it = test.iterator();
+ it.next();
+ it.next();
+ it.remove();
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(2, test.tail);
+
+ test.add("D");
+ assertEquals(5, test.buffer.length);
+ assertEquals(0, test.head);
+ assertEquals(3, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(0, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(0, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(0, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ assertEquals("C", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(3, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithTailAtEnd3() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.add("D");
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(0, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("B", it.next());
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(1, test.head);
+ assertEquals(3, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap1() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(1, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(3, test.head);
+ assertEquals(1, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap2() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(1, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(0, test.tail);
+ }
+
+ public void testInternalStateIteratorRemoveWithWrap3() {
+ UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
+ test.add("A");
+ test.add("B");
+ test.add("C");
+ test.remove("A");
+ test.remove("B");
+ test.add("D");
+ test.add("E");
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(1, test.tail);
+
+ Iterator it = test.iterator();
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ assertEquals("E", it.next());
+ it.remove();
+ assertEquals(4, test.buffer.length);
+ assertEquals(2, test.head);
+ assertEquals(0, test.tail);
+ }
+
+ //-----------------------------------------------------------------------
public String getCompatibilityVersion() {
return "3.1";
}