diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java index df7266d9e8..895ac9d014 100644 --- a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java +++ b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java @@ -1012,6 +1012,16 @@ public class DefaultHeaders> implements Headers return value; } + private void remove0(HeaderEntry entry) { + int i = index(entry.hash); + HeaderEntry e = entries[i]; + if (e == entry) { + entries[i] = entry.next; + } + entry.remove(); + --size; + } + @SuppressWarnings("unchecked") private T thisT() { return (T) this; @@ -1055,6 +1065,7 @@ public class DefaultHeaders> implements Headers private final class ValueIterator implements Iterator { private final K name; private final int hash; + private HeaderEntry previous; private HeaderEntry next; ValueIterator(K name) { @@ -1073,14 +1084,18 @@ public class DefaultHeaders> implements Headers if (!hasNext()) { throw new NoSuchElementException(); } - HeaderEntry current = next; + previous = next; calculateNext(next.next); - return current.value; + return previous.value; } @Override public void remove() { - throw new UnsupportedOperationException("read only"); + if (previous == null) { + throw new IllegalStateException(); + } + remove0(previous); + previous = null; } private void calculateNext(HeaderEntry entry) { diff --git a/codec/src/test/java/io/netty/handler/codec/DefaultHeadersTest.java b/codec/src/test/java/io/netty/handler/codec/DefaultHeadersTest.java index 2ed0498be4..b8d025c84a 100644 --- a/codec/src/test/java/io/netty/handler/codec/DefaultHeadersTest.java +++ b/codec/src/test/java/io/netty/handler/codec/DefaultHeadersTest.java @@ -121,9 +121,47 @@ public class DefaultHeadersTest { Iterator itr = headers.valueIterator(of("name")); while (itr.hasNext()) { values.add(itr.next()); + itr.remove(); } assertEquals(3, values.size()); + assertEquals(0, headers.size()); + assertTrue(headers.isEmpty()); assertTrue(values.containsAll(asList(of("value1"), of("value2"), of("value3")))); + itr = headers.valueIterator(of("name")); + assertFalse(itr.hasNext()); + } + + @Test(expected = IllegalStateException.class) + public void valuesItrRemoveThrowsWhenEmpty() { + TestDefaultHeaders headers = newInstance(); + assertEquals(0, headers.size()); + assertTrue(headers.isEmpty()); + Iterator itr = headers.valueIterator(of("name")); + itr.remove(); + } + + @Test + public void valuesItrRemoveThrowsAfterLastElement() { + TestDefaultHeaders headers = newInstance(); + headers.add(of("name"), of("value1")); + assertEquals(1, headers.size()); + + List values = new ArrayList(); + Iterator itr = headers.valueIterator(of("name")); + while (itr.hasNext()) { + values.add(itr.next()); + itr.remove(); + } + assertEquals(1, values.size()); + assertEquals(0, headers.size()); + assertTrue(headers.isEmpty()); + assertTrue(values.contains(of("value1"))); + try { + itr.remove(); + fail(); + } catch (IllegalStateException ignored) { + // ignored + } } @Test