diff --git a/codec-http2/pom.xml b/codec-http2/pom.xml
index 7eeb7fb54a..9026410a45 100644
--- a/codec-http2/pom.xml
+++ b/codec-http2/pom.xml
@@ -45,11 +45,6 @@
hpack
0.6.0
-
- com.google.guava
- guava
- 16.0.1
-
org.mockito
mockito-all
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/DefaultHttp2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/DefaultHttp2Headers.java
new file mode 100644
index 0000000000..7fda494f08
--- /dev/null
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/DefaultHttp2Headers.java
@@ -0,0 +1,513 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.http2.draft10;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * An immutable collection of headers sent or received via HTTP/2.
+ */
+public final class DefaultHttp2Headers extends Http2Headers {
+ private static final int MAX_VALUE_LENGTH = 0xFFFF; // Length is a 16-bit field
+ private static final int BUCKET_SIZE = 17;
+
+ private final HeaderEntry[] entries;
+ private final HeaderEntry head;
+
+ private DefaultHttp2Headers(Builder builder) {
+ this.entries = builder.entries;
+ this.head = builder.head;
+ }
+
+ @Override
+ public String get(String name) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+
+ int h = hash(name);
+ int i = index(h);
+ HeaderEntry e = entries[i];
+ while (e != null) {
+ if (e.hash == h && eq(name, e.key)) {
+ return e.value;
+ }
+
+ e = e.next;
+ }
+ return null;
+ }
+
+ @Override
+ public List getAll(String name) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+
+ LinkedList values = new LinkedList();
+
+ int h = hash(name);
+ int i = index(h);
+ HeaderEntry e = entries[i];
+ while (e != null) {
+ if (e.hash == h && eq(name, e.key)) {
+ values.addFirst(e.value);
+ }
+ e = e.next;
+ }
+ return values;
+ }
+
+ @Override
+ public List> entries() {
+ List> all =
+ new LinkedList>();
+
+ HeaderEntry e = head.after;
+ while (e != head) {
+ all.add(e);
+ e = e.after;
+ }
+ return all;
+ }
+
+ @Override
+ public boolean contains(String name) {
+ return get(name) != null;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return head == head.after;
+ }
+
+ @Override
+ public Set names() {
+ Set names = new TreeSet();
+
+ HeaderEntry e = head.after;
+ while (e != head) {
+ names.add(e.key);
+ e = e.after;
+ }
+ return names;
+ }
+
+ @Override
+ public Iterator> iterator() {
+ return new HeaderIterator();
+ }
+
+ /**
+ * Short cut for {@code new DefaultHttp2Headers.Builder()}.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Builds instances of {@link DefaultHttp2Header}.
+ */
+ public static class Builder {
+ private HeaderEntry[] entries;
+ private HeaderEntry head;
+ private Http2Headers buildResults;
+
+ public Builder() {
+ clear();
+ }
+
+ public void set(Http2Headers headers) {
+ // No need to lazy copy the previous results, since we're starting from scratch.
+ clear();
+ for (Map.Entry entry : headers) {
+ add(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public Builder add(final String name, final Object value) {
+ // If this is the first call on the builder since the last build, copy the previous
+ // results.
+ lazyCopy();
+
+ String lowerCaseName = name.toLowerCase();
+ validateHeaderName(lowerCaseName);
+ String strVal = toString(value);
+ validateHeaderValue(strVal);
+ int nameHash = hash(lowerCaseName);
+ int hashTableIndex = index(nameHash);
+ add0(nameHash, hashTableIndex, lowerCaseName, strVal);
+ return this;
+ }
+
+ public Builder remove(final String name) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+
+ // If this is the first call on the builder since the last build, copy the previous
+ // results.
+ lazyCopy();
+
+ String lowerCaseName = name.toLowerCase();
+ int nameHash = hash(lowerCaseName);
+ int hashTableIndex = index(nameHash);
+ remove0(nameHash, hashTableIndex, lowerCaseName);
+ return this;
+ }
+
+ public Builder set(final String name, final Object value) {
+ // If this is the first call on the builder since the last build, copy the previous
+ // results.
+ lazyCopy();
+
+ String lowerCaseName = name.toLowerCase();
+ validateHeaderName(lowerCaseName);
+ String strVal = toString(value);
+ validateHeaderValue(strVal);
+ int nameHash = hash(lowerCaseName);
+ int hashTableIndex = index(nameHash);
+ remove0(nameHash, hashTableIndex, lowerCaseName);
+ add0(nameHash, hashTableIndex, lowerCaseName, strVal);
+ return this;
+ }
+
+ public Builder set(final String name, final Iterable> values) {
+ if (values == null) {
+ throw new NullPointerException("values");
+ }
+
+ // If this is the first call on the builder since the last build, copy the previous
+ // results.
+ lazyCopy();
+
+ String lowerCaseName = name.toLowerCase();
+ validateHeaderName(lowerCaseName);
+
+ int nameHash = hash(lowerCaseName);
+ int hashTableIndex = index(nameHash);
+
+ remove0(nameHash, hashTableIndex, lowerCaseName);
+ for (Object v: values) {
+ if (v == null) {
+ break;
+ }
+ String strVal = toString(v);
+ validateHeaderValue(strVal);
+ add0(nameHash, hashTableIndex, lowerCaseName, strVal);
+ }
+ return this;
+ }
+
+ public Builder clear() {
+ // No lazy copy required, since we're just creating a new array.
+ entries = new HeaderEntry[BUCKET_SIZE];
+ head = new HeaderEntry(-1, null, null);
+ head.before = head.after = head;
+ buildResults = null;
+ return this;
+ }
+
+ /**
+ * Sets the {@link HttpName#METHOD} header.
+ */
+ public Builder setMethod(String method) {
+ return set(HttpName.METHOD.value(), method);
+ }
+
+ /**
+ * Sets the {@link HttpName#SCHEME} header.
+ */
+ public Builder setScheme(String scheme) {
+ return set(HttpName.SCHEME.value(), scheme);
+ }
+
+ /**
+ * Sets the {@link HttpName#AUTHORITY} header.
+ */
+ public Builder setAuthority(String authority) {
+ return set(HttpName.AUTHORITY.value(), authority);
+ }
+
+ /**
+ * Sets the {@link HttpName#PATH} header.
+ */
+ public Builder setPath(String path) {
+ return set(HttpName.PATH.value(), path);
+ }
+
+ /**
+ * Sets the {@link HttpName#STATUS} header.
+ */
+ public Builder setStatus(String status) {
+ return set(HttpName.STATUS.value(), status);
+ }
+
+ /**
+ * Builds a new instance of {@link DefaultHttp2Headers}.
+ */
+ public DefaultHttp2Headers build() {
+ // If this is the first call on the builder since the last build, copy the previous
+ // results.
+ lazyCopy();
+
+ // Give the multimap over to the headers instance and save the build results for
+ // future lazy copies if this builder is used again later.
+ DefaultHttp2Headers headers = new DefaultHttp2Headers(this);
+ buildResults = headers;
+ return headers;
+ }
+
+ /**
+ * Performs a lazy copy of the last build results, if there are any. For the typical use
+ * case, headers will only be built once so no copy will be required. If the any method
+ * is called on the builder after that, it will force a copy of the most recently created
+ * headers object.
+ */
+ private void lazyCopy() {
+ if (buildResults != null) {
+ set(buildResults);
+ buildResults = null;
+ }
+ }
+
+ private void add0(int hash, int hashTableIndex, final String name, final String value) {
+ // Update the hash table.
+ HeaderEntry e = entries[hashTableIndex];
+ HeaderEntry newEntry;
+ entries[hashTableIndex] = newEntry = new HeaderEntry(hash, name, value);
+ newEntry.next = e;
+
+ // Update the linked list.
+ newEntry.addBefore(head);
+ }
+
+ private void remove0(int hash, int hashTableIndex, String name) {
+ HeaderEntry e = entries[hashTableIndex];
+ if (e == null) {
+ return;
+ }
+
+ for (;;) {
+ if (e.hash == hash && eq(name, e.key)) {
+ e.remove();
+ HeaderEntry next = e.next;
+ if (next != null) {
+ entries[hashTableIndex] = next;
+ e = next;
+ } else {
+ entries[hashTableIndex] = null;
+ return;
+ }
+ } else {
+ break;
+ }
+ }
+
+ for (;;) {
+ HeaderEntry next = e.next;
+ if (next == null) {
+ break;
+ }
+ if (next.hash == hash && eq(name, next.key)) {
+ e.next = next.next;
+ next.remove();
+ } else {
+ e = next;
+ }
+ }
+ }
+
+ private static String toString(Object value) {
+ if (value == null) {
+ return null;
+ }
+ return value.toString();
+ }
+ }
+
+ private static int hash(String name) {
+ int h = 0;
+ for (int i = name.length() - 1; i >= 0; i --) {
+ char c = name.charAt(i);
+ if (c >= 'A' && c <= 'Z') {
+ c += 32;
+ }
+ h = 31 * h + c;
+ }
+
+ if (h > 0) {
+ return h;
+ } else if (h == Integer.MIN_VALUE) {
+ return Integer.MAX_VALUE;
+ } else {
+ return -h;
+ }
+ }
+
+ private static boolean eq(String name1, String name2) {
+ int nameLen = name1.length();
+ if (nameLen != name2.length()) {
+ return false;
+ }
+
+ for (int i = nameLen - 1; i >= 0; i --) {
+ char c1 = name1.charAt(i);
+ char c2 = name2.charAt(i);
+ if (c1 != c2) {
+ if (c1 >= 'A' && c1 <= 'Z') {
+ c1 += 32;
+ }
+ if (c2 >= 'A' && c2 <= 'Z') {
+ c2 += 32;
+ }
+ if (c1 != c2) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static int index(int hash) {
+ return hash % BUCKET_SIZE;
+ }
+
+ /**
+ * Validate a HTTP2 header name.
+ */
+ private static void validateHeaderName(String name) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ if (name.isEmpty()) {
+ throw new IllegalArgumentException(
+ "name cannot be length zero");
+ }
+ // Since name may only contain ascii characters, for valid names
+ // name.length() returns the number of bytes when UTF-8 encoded.
+ if (name.length() > MAX_VALUE_LENGTH) {
+ throw new IllegalArgumentException(
+ "name exceeds allowable length: " + name);
+ }
+ for (int i = 0; i < name.length(); i ++) {
+ char c = name.charAt(i);
+ if (c == 0) {
+ throw new IllegalArgumentException(
+ "name contains null character: " + name);
+ }
+ if (c > 127) {
+ throw new IllegalArgumentException(
+ "name contains non-ascii character: " + name);
+ }
+ }
+ }
+
+ /**
+ * Validate a HTTP2 header value. Does not validate max length.
+ */
+ private static void validateHeaderValue(String value) {
+ if (value == null) {
+ throw new NullPointerException("value");
+ }
+ for (int i = 0; i < value.length(); i ++) {
+ char c = value.charAt(i);
+ if (c == 0) {
+ throw new IllegalArgumentException(
+ "value contains null character: " + value);
+ }
+ }
+ }
+
+ private final class HeaderIterator implements Iterator> {
+
+ private HeaderEntry current = head;
+
+ @Override
+ public boolean hasNext() {
+ return current.after != head;
+ }
+
+ @Override
+ public Entry next() {
+ current = current.after;
+
+ if (current == head) {
+ throw new NoSuchElementException();
+ }
+
+ return current;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class HeaderEntry implements Map.Entry {
+ final int hash;
+ final String key;
+ final String value;
+ HeaderEntry next;
+ HeaderEntry before, after;
+
+ HeaderEntry(int hash, String key, String value) {
+ this.hash = hash;
+ this.key = key;
+ this.value = value;
+ }
+
+ void remove() {
+ before.after = after;
+ after.before = before;
+ }
+
+ void addBefore(HeaderEntry e) {
+ after = e;
+ before = e.before;
+ before.after = this;
+ after.before = this;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String setValue(String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString() {
+ return key + '=' + value;
+ }
+ }
+}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/Http2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/Http2Headers.java
index 65826c4b76..478c13a7da 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/Http2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/Http2Headers.java
@@ -15,14 +15,57 @@
package io.netty.handler.codec.http2.draft10;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
import java.util.Map.Entry;
+import java.util.Set;
-import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMultimap;
+/**
+ * An immutable collection of headers sent or received via HTTP/2.
+ */
+public abstract class Http2Headers implements Iterable> {
-public final class Http2Headers implements Iterable> {
+ public static final Http2Headers EMPTY_HEADERS = new Http2Headers() {
+
+ @Override
+ public String get(String name) {
+ return null;
+ }
+
+ @Override
+ public List getAll(String name) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List> entries() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean contains(String name) {
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
+ @Override
+ public Set names() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Iterator> iterator() {
+ return entries().iterator();
+ }
+ };
/**
* HTTP2 header names.
@@ -64,130 +107,136 @@ public final class Http2Headers implements Iterable> {
}
}
- private final ImmutableMultimap headers;
+ /**
+ * Returns the {@link Set} of all header names.
+ */
+ public abstract Set names();
- private Http2Headers(Builder builder) {
- this.headers = builder.map.build();
+ /**
+ * Returns the header value with the specified header name. If there is
+ * more than one header value for the specified header name, the first
+ * value is returned.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public abstract String get(String name);
+
+ /**
+ * Returns the header values with the specified header name.
+ *
+ * @return the {@link List} of header values. An empty list if there is no
+ * such header.
+ */
+ public abstract List getAll(String name);
+
+ /**
+ * Returns all header names and values that this frame contains.
+ *
+ * @return the {@link List} of the header name-value pairs. An empty list
+ * if there is no header in this message.
+ */
+ public abstract List> entries();
+
+ /**
+ * Returns {@code true} if and only if there is a header with the specified
+ * header name.
+ */
+ public abstract boolean contains(String name);
+
+ /**
+ * Checks if no header exists.
+ */
+ public abstract boolean isEmpty();
+
+ /**
+ * Gets the {@link HttpName#METHOD} header.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public final String getMethod() {
+ return get(HttpName.METHOD.value());
}
- public String getHeader(String name) {
- ImmutableCollection col = getHeaders(name);
- return col.isEmpty() ? null : col.iterator().next();
+ /**
+ * Gets the {@link HttpName#SCHEME} header.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public final String getScheme() {
+ return get(HttpName.SCHEME.value());
}
- public ImmutableCollection getHeaders(String name) {
- return headers.get(name);
+ /**
+ * Gets the {@link HttpName#AUTHORITY} header.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public final String getAuthority() {
+ return get(HttpName.AUTHORITY.value());
}
- public String getMethod() {
- return getHeader(HttpName.METHOD.value());
+ /**
+ * Gets the {@link HttpName#PATH} header.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public final String getPath() {
+ return get(HttpName.PATH.value());
}
- public String getScheme() {
- return getHeader(HttpName.SCHEME.value());
- }
-
- public String getAuthority() {
- return getHeader(HttpName.AUTHORITY.value());
- }
-
- public String getPath() {
- return getHeader(HttpName.PATH.value());
- }
-
- public String getStatus() {
- return getHeader(HttpName.STATUS.value());
- }
-
- @Override
- public Iterator> iterator() {
- return headers.entries().iterator();
+ /**
+ * Gets the {@link HttpName#STATUS} header.
+ *
+ * @return the header value or {@code null} if there is no such header
+ */
+ public final String getStatus() {
+ return get(HttpName.STATUS.value());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((headers == null) ? 0 : headers.hashCode());
+ for (String name : names()) {
+ result = prime * result + name.hashCode();
+ Set values = new TreeSet(getAll(name));
+ for (String value : values) {
+ result = prime * result + value.hashCode();
+ }
+ }
return result;
}
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
+ public boolean equals(Object o) {
+ if (!(o instanceof Http2Headers)) {
return false;
}
- if (getClass() != obj.getClass()) {
+ Http2Headers other = (Http2Headers) o;
+
+ // First, check that the set of names match.
+ Set names = names();
+ if (!names.equals(other.names())) {
return false;
}
- Http2Headers other = (Http2Headers) obj;
- if (headers == null) {
- if (other.headers != null) {
+
+ // Compare the values for each name.
+ for (String name : names) {
+ List values = getAll(name);
+ List otherValues = other.getAll(name);
+ if (values.size() != otherValues.size()) {
+ return false;
+ }
+ // Convert the values to a set and remove values from the other object to see if
+ // they match.
+ Set valueSet = new HashSet(values);
+ valueSet.removeAll(otherValues);
+ if (!valueSet.isEmpty()) {
return false;
}
- } else if (!headers.equals(other.headers)) {
- return false;
}
+
+ // They match.
return true;
}
-
- @Override
- public String toString() {
- return headers.toString();
- }
-
- public static class Builder {
- private ImmutableMultimap.Builder map = ImmutableMultimap.builder();
-
- public Builder clear() {
- map = ImmutableMultimap.builder();
- return this;
- }
-
- public Builder addHeaders(Http2Headers headers) {
- if (headers == null) {
- throw new IllegalArgumentException("headers must not be null.");
- }
- map.putAll(headers.headers);
- return this;
- }
-
- public Builder addHeader(String name, String value) {
- // Use interning on the header name to save space.
- map.put(name.intern(), value);
- return this;
- }
-
- public Builder addHeader(byte[] name, byte[] value) {
- addHeader(new String(name, Charsets.UTF_8), new String(value, Charsets.UTF_8));
- return this;
- }
-
- public Builder setMethod(String value) {
- return addHeader(HttpName.METHOD.value(), value);
- }
-
- public Builder setScheme(String value) {
- return addHeader(HttpName.SCHEME.value(), value);
- }
-
- public Builder setAuthority(String value) {
- return addHeader(HttpName.AUTHORITY.value(), value);
- }
-
- public Builder setPath(String value) {
- return addHeader(HttpName.PATH.value(), value);
- }
-
- public Builder setStatus(String value) {
- return addHeader(HttpName.STATUS.value(), value);
- }
-
- public Http2Headers build() {
- return new Http2Headers(this);
- }
- }
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2Connection.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2Connection.java
index 94af51acb4..97b7c79755 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2Connection.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2Connection.java
@@ -20,7 +20,6 @@ import static io.netty.handler.codec.http2.draft10.Http2Exception.format;
import static io.netty.handler.codec.http2.draft10.Http2Exception.protocolError;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.toByteBuf;
import static io.netty.handler.codec.http2.draft10.frame.Http2FrameCodecUtil.DEFAULT_STREAM_PRIORITY;
-
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
@@ -32,23 +31,37 @@ import io.netty.handler.codec.http2.draft10.connection.Http2Stream.State;
import io.netty.handler.codec.http2.draft10.frame.DefaultHttp2GoAwayFrame;
import io.netty.handler.codec.http2.draft10.frame.Http2GoAwayFrame;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.TreeMultiset;
+import java.util.Set;
+import java.util.TreeSet;
public class DefaultHttp2Connection implements Http2Connection {
+ /**
+ * Used to sort streams in the activeStreams set. Sort by priority first, then by stream ID.
+ * Streams with the same ID are considered equal.
+ */
+ private static final Comparator STREAM_COMPARATOR = new Comparator() {
+ @Override
+ public int compare(Http2Stream s1, Http2Stream s2) {
+ int p1 = s1.getPriority();
+ int p2 = s2.getPriority();
- private final List listeners = Lists.newArrayList();
- private final Map streamMap = Maps.newHashMap();
- private final Multiset activeStreams = TreeMultiset.create();
+ // Sort streams with the same priority by their ID.
+ if (p1 == p2) {
+ return s1.getId() - s2.getId();
+ }
+ return p1 - p2;
+ }
+ };
+
+ private final List listeners = new ArrayList();
+ private final Map streamMap = new HashMap();
+ private final Set activeStreams = new TreeSet(STREAM_COMPARATOR);
private final DefaultEndpoint localEndpoint;
private final DefaultEndpoint remoteEndpoint;
private boolean goAwaySent;
@@ -85,10 +98,10 @@ public class DefaultHttp2Connection implements Http2Connection {
}
@Override
- public List getActiveStreams() {
+ public Set getActiveStreams() {
// Copy the list in case any operation on the returned streams causes the activeStreams set
// to change.
- return ImmutableList.copyOf(activeStreams);
+ return Collections.unmodifiableSet(activeStreams);
}
@Override
@@ -181,21 +194,14 @@ public class DefaultHttp2Connection implements Http2Connection {
return state;
}
- @Override
- public int compareTo(Http2Stream other) {
- // Sort streams with the same priority by their ID.
- if (priority == other.getPriority()) {
- return id - other.getId();
- }
- return priority - other.getPriority();
- }
-
@Override
public void verifyState(Http2Error error, State... allowedStates) throws Http2Exception {
- Predicate predicate = Predicates.in(Arrays.asList(allowedStates));
- if (!predicate.apply(state)) {
- throw format(error, "Stream %d in unexpected state: %s", id, state);
+ for (State allowedState : allowedStates) {
+ if (state == allowedState) {
+ return;
+ }
}
+ throw format(error, "Stream %d in unexpected state: %s", id, state);
}
@Override
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultInboundFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultInboundFlowController.java
index 79466074d9..ca29588dcf 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultInboundFlowController.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultInboundFlowController.java
@@ -19,16 +19,14 @@ import static io.netty.handler.codec.http2.draft10.Http2Exception.flowControlErr
import static io.netty.handler.codec.http2.draft10.Http2Exception.protocolError;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.DEFAULT_FLOW_CONTROL_WINDOW_SIZE;
import static io.netty.handler.codec.http2.draft10.frame.Http2FrameCodecUtil.CONNECTION_STREAM_ID;
-
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.frame.DefaultHttp2WindowUpdateFrame;
import io.netty.handler.codec.http2.draft10.frame.Http2DataFrame;
import io.netty.handler.codec.http2.draft10.frame.Http2WindowUpdateFrame;
+import java.util.HashMap;
import java.util.Map;
-import com.google.common.collect.Maps;
-
/**
* Basic implementation of {@link InboundFlowController}.
*/
@@ -36,7 +34,7 @@ public class DefaultInboundFlowController implements InboundFlowController {
private int initialWindowSize = DEFAULT_FLOW_CONTROL_WINDOW_SIZE;
private final StreamWindow connectionWindow = new StreamWindow(CONNECTION_STREAM_ID);
- private final Map streamWindows = Maps.newHashMap();
+ private final Map streamWindows = new HashMap();
public DefaultInboundFlowController(Http2Connection connection) {
connection.addListener(new Http2Connection.Listener() {
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowController.java
index 5d458f1be0..031dc27bc7 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowController.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowController.java
@@ -21,25 +21,23 @@ import static io.netty.handler.codec.http2.draft10.Http2Exception.format;
import static io.netty.handler.codec.http2.draft10.Http2Exception.protocolError;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.DEFAULT_FLOW_CONTROL_WINDOW_SIZE;
import static io.netty.handler.codec.http2.draft10.frame.Http2FrameCodecUtil.CONNECTION_STREAM_ID;
-
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.Http2StreamException;
import io.netty.handler.codec.http2.draft10.frame.DefaultHttp2DataFrame;
import io.netty.handler.codec.http2.draft10.frame.Http2DataFrame;
+import java.util.ArrayDeque;
+import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
/**
* Basic implementation of {@link OutboundFlowController}.
*/
public class DefaultOutboundFlowController implements OutboundFlowController {
private final Http2Connection connection;
- private final Map streamStates = Maps.newHashMap();
+ private final Map streamStates = new HashMap();
private int initialWindowSize = DEFAULT_FLOW_CONTROL_WINDOW_SIZE;
private int connectionWindowSize = DEFAULT_FLOW_CONTROL_WINDOW_SIZE;
@@ -185,7 +183,7 @@ public class DefaultOutboundFlowController implements OutboundFlowController {
*/
private class StreamState {
private final int streamId;
- private final Queue pendingWriteQueue = Lists.newLinkedList();
+ private final Queue pendingWriteQueue = new ArrayDeque();
private int windowSize = initialWindowSize;
public StreamState(int streamId) {
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Connection.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Connection.java
index 28a0517583..b5a4e7e89a 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Connection.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Connection.java
@@ -19,7 +19,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http2.draft10.Http2Exception;
-import java.util.List;
+import java.util.Collection;
public interface Http2Connection {
@@ -132,7 +132,7 @@ public interface Http2Connection {
* Gets all streams that are currently either open or half-closed. The returned collection is
* sorted by priority.
*/
- List getActiveStreams();
+ Collection getActiveStreams();
/**
* Gets a view of this connection from the local {@link Endpoint}.
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Stream.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Stream.java
index 7fe5f68e9c..1f481f7fb6 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Stream.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/connection/Http2Stream.java
@@ -23,7 +23,7 @@ import io.netty.handler.codec.http2.draft10.Http2Exception;
/**
* A single stream within an HTTP2 connection. Streams are compared to each other by priority.
*/
-public interface Http2Stream extends Comparable {
+public interface Http2Stream {
/**
* The allowed states of an HTTP2 stream.
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2HeadersFrame.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2HeadersFrame.java
index f4133ae810..d5b5c0c759 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2HeadersFrame.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2HeadersFrame.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http2.draft10.frame;
import static io.netty.handler.codec.http2.draft10.frame.Http2FrameCodecUtil.DEFAULT_STREAM_PRIORITY;
-
+import io.netty.handler.codec.http2.draft10.DefaultHttp2Headers;
import io.netty.handler.codec.http2.draft10.Http2Headers;
public final class DefaultHttp2HeadersFrame implements Http2HeadersFrame {
@@ -104,7 +104,7 @@ public final class DefaultHttp2HeadersFrame implements Http2HeadersFrame {
public static class Builder {
private int streamId;
private int priority = DEFAULT_STREAM_PRIORITY;
- private final Http2Headers.Builder headersBuilder = new Http2Headers.Builder();
+ private final DefaultHttp2Headers.Builder headersBuilder = new DefaultHttp2Headers.Builder();
private boolean endOfStream;
public Builder setStreamId(int streamId) {
@@ -128,12 +128,12 @@ public final class DefaultHttp2HeadersFrame implements Http2HeadersFrame {
return this;
}
- public Http2Headers.Builder headers() {
+ public DefaultHttp2Headers.Builder headers() {
return headersBuilder;
}
public Builder setHeaders(Http2Headers headers) {
- headersBuilder.addHeaders(headers);
+ headersBuilder.set(headers);
return this;
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/DefaultHttp2HeadersDecoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/DefaultHttp2HeadersDecoder.java
index d231296945..5775c5c288 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/DefaultHttp2HeadersDecoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/DefaultHttp2HeadersDecoder.java
@@ -17,12 +17,13 @@ package io.netty.handler.codec.http2.draft10.frame.decoder;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.DEFAULT_HEADER_TABLE_SIZE;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.DEFAULT_MAX_HEADER_SIZE;
-
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
+import io.netty.handler.codec.http2.draft10.DefaultHttp2Headers;
import io.netty.handler.codec.http2.draft10.Http2Error;
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.Http2Headers;
+import io.netty.util.CharsetUtil;
import java.io.IOException;
@@ -45,11 +46,12 @@ public class DefaultHttp2HeadersDecoder implements Http2HeadersDecoder {
@Override
public Http2Headers decodeHeaders(ByteBuf headerBlock) throws Http2Exception {
try {
- final Http2Headers.Builder headersBuilder = new Http2Headers.Builder();
+ final DefaultHttp2Headers.Builder headersBuilder = new DefaultHttp2Headers.Builder();
HeaderListener listener = new HeaderListener() {
@Override
public void emitHeader(byte[] key, byte[] value) {
- headersBuilder.addHeader(key, value);
+ headersBuilder.add(new String(key, CharsetUtil.UTF_8), new String(value,
+ CharsetUtil.UTF_8));
}
};
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2HeadersFrameUnmarshaller.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2HeadersFrameUnmarshaller.java
index f17c1a2c03..5beff990a6 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2HeadersFrameUnmarshaller.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2HeadersFrameUnmarshaller.java
@@ -31,8 +31,6 @@ import io.netty.handler.codec.http2.draft10.frame.Http2Frame;
import io.netty.handler.codec.http2.draft10.frame.Http2FrameHeader;
import io.netty.handler.codec.http2.draft10.frame.Http2HeadersFrame;
-import com.google.common.base.Preconditions;
-
/**
* An unmarshaller for {@link Http2HeadersFrame} instances.
*/
@@ -41,7 +39,10 @@ public class Http2HeadersFrameUnmarshaller extends AbstractHeadersUnmarshaller {
private final Http2HeadersDecoder headersDecoder;
public Http2HeadersFrameUnmarshaller(Http2HeadersDecoder headersDecoder) {
- this.headersDecoder = Preconditions.checkNotNull(headersDecoder, "headersDecoder");
+ if (headersDecoder == null) {
+ throw new IllegalArgumentException("headersDecoder must not be null.");
+ }
+ this.headersDecoder = headersDecoder;
}
@Override
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2PushPromiseFrameUnmarshaller.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2PushPromiseFrameUnmarshaller.java
index 5c13fec8cf..4080603f43 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2PushPromiseFrameUnmarshaller.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/decoder/Http2PushPromiseFrameUnmarshaller.java
@@ -30,8 +30,6 @@ import io.netty.handler.codec.http2.draft10.frame.Http2Frame;
import io.netty.handler.codec.http2.draft10.frame.Http2FrameHeader;
import io.netty.handler.codec.http2.draft10.frame.Http2PushPromiseFrame;
-import com.google.common.base.Preconditions;
-
/**
* An unmarshaller for {@link Http2PushPromiseFrame} instances.
*/
@@ -40,7 +38,10 @@ public class Http2PushPromiseFrameUnmarshaller extends AbstractHeadersUnmarshall
private final Http2HeadersDecoder headersDecoder;
public Http2PushPromiseFrameUnmarshaller(Http2HeadersDecoder headersDecoder) {
- this.headersDecoder = Preconditions.checkNotNull(headersDecoder, "headersDecoder");
+ if (headersDecoder == null) {
+ throw new IllegalArgumentException("headersDecoder must not be null.");
+ }
+ this.headersDecoder = headersDecoder;
}
@Override
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/DefaultHttp2HeadersEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/DefaultHttp2HeadersEncoder.java
index 4331c16475..2c63d337a6 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/DefaultHttp2HeadersEncoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/DefaultHttp2HeadersEncoder.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http2.draft10.frame.encoder;
import static io.netty.handler.codec.http2.draft10.connection.Http2ConnectionUtil.DEFAULT_HEADER_TABLE_SIZE;
-
+import static io.netty.util.CharsetUtil.UTF_8;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.handler.codec.http2.draft10.Http2Error;
@@ -25,14 +25,11 @@ import io.netty.handler.codec.http2.draft10.Http2Headers;
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.charset.Charset;
import java.util.Map.Entry;
-import com.google.common.base.Charsets;
import com.twitter.hpack.Encoder;
public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder {
- private static final Charset DEFAULT_CHARSET = Charsets.UTF_8;
private final Encoder encoder;
@@ -45,8 +42,8 @@ public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder {
try {
OutputStream stream = new ByteBufOutputStream(buffer);
for (Entry header : headers) {
- byte[] key = header.getKey().getBytes(DEFAULT_CHARSET);
- byte[] value = header.getValue().getBytes(DEFAULT_CHARSET);
+ byte[] key = header.getKey().getBytes(UTF_8);
+ byte[] value = header.getValue().getBytes(UTF_8);
encoder.encodeHeader(stream, key, value);
}
encoder.endHeaders(stream);
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2HeadersFrameMarshaller.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2HeadersFrameMarshaller.java
index 1d6474c4af..7fb90973d2 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2HeadersFrameMarshaller.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2HeadersFrameMarshaller.java
@@ -29,15 +29,16 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.frame.Http2HeadersFrame;
-import com.google.common.base.Preconditions;
-
public class Http2HeadersFrameMarshaller extends AbstractHttp2FrameMarshaller {
private final Http2HeadersEncoder headersEncoder;
public Http2HeadersFrameMarshaller(Http2HeadersEncoder headersEncoder) {
super(Http2HeadersFrame.class);
- this.headersEncoder = Preconditions.checkNotNull(headersEncoder, "headersEncoder");
+ if (headersEncoder == null) {
+ throw new NullPointerException("headersEncoder must not be null.");
+ }
+ this.headersEncoder = headersEncoder;
}
@Override
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2PushPromiseFrameMarshaller.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2PushPromiseFrameMarshaller.java
index 21de2f1160..78cb7ad9ba 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2PushPromiseFrameMarshaller.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/frame/encoder/Http2PushPromiseFrameMarshaller.java
@@ -26,8 +26,6 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.frame.Http2PushPromiseFrame;
-import com.google.common.base.Preconditions;
-
public class Http2PushPromiseFrameMarshaller extends
AbstractHttp2FrameMarshaller {
@@ -35,7 +33,10 @@ public class Http2PushPromiseFrameMarshaller extends
public Http2PushPromiseFrameMarshaller(Http2HeadersEncoder headersEncoder) {
super(Http2PushPromiseFrame.class);
- this.headersEncoder = Preconditions.checkNotNull(headersEncoder, "headersEncoder");
+ if (headersEncoder == null) {
+ throw new NullPointerException("headersEncoder must not be null.");
+ }
+ this.headersEncoder = headersEncoder;
}
@Override
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/DefaultHttp2HeadersTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/DefaultHttp2HeadersTest.java
new file mode 100644
index 0000000000..4ed9b9ee16
--- /dev/null
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/DefaultHttp2HeadersTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.http2.draft10;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.junit.Test;
+
+
+/**
+ * Tests for {@link DefaultHttp2Headers}.
+ */
+public class DefaultHttp2HeadersTest {
+
+ @Test
+ public void duplicateKeysShouldStoreAllValues() {
+ DefaultHttp2Headers headers =
+ DefaultHttp2Headers.newBuilder().add("a", "1").add("a", "2")
+ .add("a", "3").build();
+ List aValues = headers.getAll("a");
+ assertEquals(3, aValues.size());
+ assertEquals("1", aValues.get(0));
+ assertEquals("2", aValues.get(1));
+ assertEquals("3", aValues.get(2));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void iterateEmptyHeadersShouldThrow() {
+ Iterator> iterator =
+ DefaultHttp2Headers.newBuilder().build().iterator();
+ assertFalse(iterator.hasNext());
+ iterator.next();
+ }
+
+ @Test
+ public void iterateHeadersShouldReturnAllValues() {
+ Set headers = new HashSet();
+ headers.add("a:1");
+ headers.add("a:2");
+ headers.add("a:3");
+ headers.add("b:1");
+ headers.add("b:2");
+ headers.add("c:1");
+
+ // Build the headers from the input set.
+ DefaultHttp2Headers.Builder builder = DefaultHttp2Headers.newBuilder();
+ for (String header : headers) {
+ String[] parts = header.split(":");
+ builder.add(parts[0], parts[1]);
+ }
+
+ // Now iterate through the headers, removing them from the original set.
+ for (Map.Entry entry : builder.build()) {
+ assertTrue(headers.remove(entry.getKey() + ":" + entry.getValue()));
+ }
+
+ // Make sure we removed them all.
+ assertTrue(headers.isEmpty());
+ }
+}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2ConnectionTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2ConnectionTest.java
index 6787c374e5..8ebd2d747f 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2ConnectionTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultHttp2ConnectionTest.java
@@ -32,6 +32,7 @@ import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.connection.Http2Connection.Listener;
import io.netty.handler.codec.http2.draft10.connection.Http2Stream.State;
+import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
@@ -225,7 +226,7 @@ public class DefaultHttp2ConnectionTest {
server.local().createStream(4, 256, true);
server.remote().createStream(3, Integer.MAX_VALUE, true);
server.remote().createStream(5, 1, false);
- List activeStreams = server.getActiveStreams();
+ List activeStreams = activeStreams();
assertEquals(2, activeStreams.get(0).getId());
assertEquals(5, activeStreams.get(1).getId());
assertEquals(4, activeStreams.get(2).getId());
@@ -244,7 +245,7 @@ public class DefaultHttp2ConnectionTest {
// Make this this highest priority.
stream7.setPriority(0);
- List activeStreams = server.getActiveStreams();
+ List activeStreams = activeStreams();
assertEquals(7, activeStreams.get(0).getId());
assertEquals(2, activeStreams.get(1).getId());
assertEquals(5, activeStreams.get(2).getId());
@@ -305,4 +306,8 @@ public class DefaultHttp2ConnectionTest {
stream.close(ctx, future);
verify(ctx).close(promise);
}
+
+ private List activeStreams() {
+ return new ArrayList(server.getActiveStreams());
+ }
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowControllerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowControllerTest.java
index 242e8b8eb6..c1889549d7 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowControllerTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/DefaultOutboundFlowControllerTest.java
@@ -23,6 +23,9 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http2.draft10.Http2Exception;
@@ -39,8 +42,6 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import com.google.common.collect.ImmutableList;
-
/**
* Tests for {@link DefaultOutboundFlowController}.
*/
@@ -74,7 +75,7 @@ public class DefaultOutboundFlowControllerTest {
return null;
}
}).when(connection).addListener(any(Listener.class));
- when(connection.getActiveStreams()).thenReturn(ImmutableList.of(stream));
+ when(connection.getActiveStreams()).thenReturn(Arrays.asList(stream));
when(stream.getId()).thenReturn(STREAM_ID);
controller = new DefaultOutboundFlowController(connection);
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/Http2ConnectionHandlerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/Http2ConnectionHandlerTest.java
index 4632381e33..00c4d36d1b 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/Http2ConnectionHandlerTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/connection/Http2ConnectionHandlerTest.java
@@ -17,6 +17,7 @@ package io.netty.handler.codec.http2.draft10.connection;
import static io.netty.handler.codec.http2.draft10.Http2Error.PROTOCOL_ERROR;
import static io.netty.handler.codec.http2.draft10.frame.Http2FrameCodecUtil.PING_FRAME_PAYLOAD_LENGTH;
+import static io.netty.util.CharsetUtil.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@@ -51,15 +52,13 @@ import io.netty.handler.codec.http2.draft10.frame.Http2Frame;
import io.netty.handler.codec.http2.draft10.frame.Http2PingFrame;
import io.netty.handler.codec.http2.draft10.frame.Http2SettingsFrame;
-import java.nio.charset.Charset;
+import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import com.google.common.collect.ImmutableList;
-
/**
* Tests for {@link Http2ConnectionHandler}.
*/
@@ -111,7 +110,7 @@ public class Http2ConnectionHandlerTest {
when(channel.isActive()).thenReturn(true);
when(stream.getId()).thenReturn(STREAM_ID);
when(pushStream.getId()).thenReturn(PUSH_STREAM_ID);
- when(connection.getActiveStreams()).thenReturn(ImmutableList.of(stream));
+ when(connection.getActiveStreams()).thenReturn(Arrays.asList(stream));
when(connection.getStream(STREAM_ID)).thenReturn(stream);
when(connection.getStreamOrFail(STREAM_ID)).thenReturn(stream);
when(connection.local()).thenReturn(local);
@@ -157,7 +156,7 @@ public class Http2ConnectionHandlerTest {
@Test
public void inboundDataAfterGoAwayShouldApplyFlowControl() throws Exception {
when(connection.isGoAwaySent()).thenReturn(true);
- ByteBuf data = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
+ ByteBuf data = Unpooled.copiedBuffer("Hello", UTF_8);
Http2DataFrame frame =
new DefaultHttp2DataFrame.Builder().setStreamId(STREAM_ID).setContent(data).build();
handler.channelRead(ctx, frame);
@@ -168,7 +167,7 @@ public class Http2ConnectionHandlerTest {
@Test
public void inboundDataWithEndOfStreamShouldCloseRemoteSide() throws Exception {
- ByteBuf data = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
+ ByteBuf data = Unpooled.copiedBuffer("Hello", UTF_8);
Http2DataFrame frame =
new DefaultHttp2DataFrame.Builder().setStreamId(STREAM_ID).setEndOfStream(true)
.setContent(data).build();
@@ -182,7 +181,7 @@ public class Http2ConnectionHandlerTest {
@Test
public void inboundDataShouldSucceed() throws Exception {
- ByteBuf data = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
+ ByteBuf data = Unpooled.copiedBuffer("Hello", UTF_8);
Http2DataFrame frame =
new DefaultHttp2DataFrame.Builder().setStreamId(STREAM_ID).setContent(data).build();
handler.channelRead(ctx, frame);
@@ -198,7 +197,7 @@ public class Http2ConnectionHandlerTest {
when(connection.isGoAwaySent()).thenReturn(true);
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.channelRead(ctx, frame);
verify(remote, never()).createStream(eq(STREAM_ID), eq(1), eq(false));
verify(ctx, never()).fireChannelRead(frame);
@@ -209,7 +208,7 @@ public class Http2ConnectionHandlerTest {
int newStreamId = 5;
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(newStreamId).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.channelRead(ctx, frame);
verify(remote).createStream(eq(newStreamId), eq(1), eq(false));
verify(ctx).fireChannelRead(frame);
@@ -220,7 +219,7 @@ public class Http2ConnectionHandlerTest {
int newStreamId = 5;
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(newStreamId).setPriority(1)
- .setEndOfStream(true).setHeaders(new Http2Headers.Builder().build())
+ .setEndOfStream(true).setHeaders(Http2Headers.EMPTY_HEADERS)
.build();
handler.channelRead(ctx, frame);
verify(remote).createStream(eq(newStreamId), eq(1), eq(true));
@@ -231,7 +230,7 @@ public class Http2ConnectionHandlerTest {
public void inboundHeadersWithForPromisedStreamShouldHalfOpenStream() throws Exception {
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.channelRead(ctx, frame);
verify(stream).openForPush();
verify(ctx).fireChannelRead(frame);
@@ -241,7 +240,7 @@ public class Http2ConnectionHandlerTest {
public void inboundHeadersWithForPromisedStreamShouldCloseStream() throws Exception {
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setEndOfStream(true).setHeaders(new Http2Headers.Builder().build())
+ .setEndOfStream(true).setHeaders(Http2Headers.EMPTY_HEADERS)
.build();
handler.channelRead(ctx, frame);
verify(stream).openForPush();
@@ -255,7 +254,7 @@ public class Http2ConnectionHandlerTest {
Http2Frame frame =
new DefaultHttp2PushPromiseFrame.Builder().setStreamId(STREAM_ID)
.setPromisedStreamId(PUSH_STREAM_ID)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.channelRead(ctx, frame);
verify(remote, never()).reservePushStream(eq(PUSH_STREAM_ID), eq(stream));
verify(ctx, never()).fireChannelRead(frame);
@@ -266,7 +265,7 @@ public class Http2ConnectionHandlerTest {
Http2Frame frame =
new DefaultHttp2PushPromiseFrame.Builder().setStreamId(STREAM_ID)
.setPromisedStreamId(PUSH_STREAM_ID)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.channelRead(ctx, frame);
verify(remote).reservePushStream(eq(PUSH_STREAM_ID), eq(stream));
verify(ctx).fireChannelRead(frame);
@@ -419,7 +418,7 @@ public class Http2ConnectionHandlerTest {
@Test
public void outboundDataAfterGoAwayShouldFail() throws Exception {
when(connection.isGoAway()).thenReturn(true);
- ByteBuf data = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
+ ByteBuf data = Unpooled.copiedBuffer("Hello", UTF_8);
Http2DataFrame frame =
new DefaultHttp2DataFrame.Builder().setStreamId(STREAM_ID).setContent(data).build();
handler.write(ctx, frame, promise);
@@ -431,7 +430,7 @@ public class Http2ConnectionHandlerTest {
@Test
public void outboundDataShouldApplyFlowControl() throws Exception {
- ByteBuf data = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
+ ByteBuf data = Unpooled.copiedBuffer("Hello", UTF_8);
Http2DataFrame frame =
new DefaultHttp2DataFrame.Builder().setStreamId(STREAM_ID).setContent(data).build();
handler.write(ctx, frame, promise);
@@ -447,7 +446,7 @@ public class Http2ConnectionHandlerTest {
when(connection.isGoAway()).thenReturn(true);
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.write(ctx, frame, promise);
verify(promise).setFailure(any(Http2Exception.class));
verify(ctx, never()).writeAndFlush(frame, promise);
@@ -458,7 +457,7 @@ public class Http2ConnectionHandlerTest {
int newStreamId = 5;
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(newStreamId).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.write(ctx, frame, promise);
verify(local).createStream(eq(newStreamId), eq(1), eq(false));
verify(promise, never()).setFailure(any(Http2Exception.class));
@@ -470,7 +469,7 @@ public class Http2ConnectionHandlerTest {
int newStreamId = 5;
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(newStreamId).setPriority(1)
- .setEndOfStream(true).setHeaders(new Http2Headers.Builder().build())
+ .setEndOfStream(true).setHeaders(Http2Headers.EMPTY_HEADERS)
.build();
handler.write(ctx, frame, promise);
verify(local).createStream(eq(newStreamId), eq(1), eq(true));
@@ -482,7 +481,7 @@ public class Http2ConnectionHandlerTest {
public void outboundHeadersShouldOpenStreamForPush() throws Exception {
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.write(ctx, frame, promise);
verify(stream).openForPush();
verify(stream, never()).closeLocalSide(eq(ctx), eq(future));
@@ -494,7 +493,7 @@ public class Http2ConnectionHandlerTest {
public void outboundHeadersShouldClosePushStream() throws Exception {
Http2Frame frame =
new DefaultHttp2HeadersFrame.Builder().setStreamId(STREAM_ID).setPriority(1)
- .setEndOfStream(true).setHeaders(new Http2Headers.Builder().build())
+ .setEndOfStream(true).setHeaders(Http2Headers.EMPTY_HEADERS)
.build();
handler.write(ctx, frame, promise);
verify(stream).openForPush();
@@ -509,7 +508,7 @@ public class Http2ConnectionHandlerTest {
Http2Frame frame =
new DefaultHttp2PushPromiseFrame.Builder().setStreamId(STREAM_ID)
.setPromisedStreamId(PUSH_STREAM_ID)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.write(ctx, frame, promise);
verify(promise).setFailure(any(Http2Exception.class));
verify(local, never()).reservePushStream(eq(PUSH_STREAM_ID), eq(stream));
@@ -521,7 +520,7 @@ public class Http2ConnectionHandlerTest {
Http2Frame frame =
new DefaultHttp2PushPromiseFrame.Builder().setStreamId(STREAM_ID)
.setPromisedStreamId(PUSH_STREAM_ID)
- .setHeaders(new Http2Headers.Builder().build()).build();
+ .setHeaders(Http2Headers.EMPTY_HEADERS).build();
handler.write(ctx, frame, promise);
verify(promise, never()).setFailure(any(Http2Exception.class));
verify(local).reservePushStream(eq(PUSH_STREAM_ID), eq(stream));
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/Http2FrameRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2FrameRoundtripTest.java
similarity index 95%
rename from codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/Http2FrameRoundtripTest.java
rename to codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2FrameRoundtripTest.java
index 434edb7d74..608108e73a 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/Http2FrameRoundtripTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/DefaultHttp2FrameRoundtripTest.java
@@ -15,6 +15,7 @@
package io.netty.handler.codec.http2.draft10.frame;
+import static io.netty.util.CharsetUtil.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -33,6 +34,7 @@ import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http2.draft10.DefaultHttp2Headers;
import io.netty.handler.codec.http2.draft10.Http2Headers;
import io.netty.util.NetUtil;
import io.netty.util.ReferenceCountUtil;
@@ -44,12 +46,10 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
-import com.google.common.base.Charsets;
-
/**
* Tests encoding/decoding each HTTP2 frame type.
*/
-public class Http2FrameRoundtripTest {
+public class DefaultHttp2FrameRoundtripTest {
private static final EventLoopGroup group = new NioEventLoopGroup();
@@ -121,7 +121,7 @@ public class Http2FrameRoundtripTest {
@Test
public void headersFrameWithoutPriorityShouldMatch() throws Exception {
Http2Headers headers =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2").build();
Http2HeadersFrame in =
new DefaultHttp2HeadersFrame.Builder().setHeaders(headers).setEndOfStream(true)
@@ -134,7 +134,7 @@ public class Http2FrameRoundtripTest {
@Test
public void headersFrameWithPriorityShouldMatch() throws Exception {
Http2Headers headers =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2").build();
Http2HeadersFrame in =
new DefaultHttp2HeadersFrame.Builder().setHeaders(headers).setEndOfStream(true)
@@ -158,7 +158,7 @@ public class Http2FrameRoundtripTest {
@Test
public void pingFrameShouldMatch() throws Exception {
- ByteBuf buf = Unpooled.copiedBuffer("01234567", Charsets.UTF_8);
+ ByteBuf buf = Unpooled.copiedBuffer("01234567", UTF_8);
Http2PingFrame in =
new DefaultHttp2PingFrame.Builder().setAck(true).setData(buf).build().retain();
@@ -180,7 +180,7 @@ public class Http2FrameRoundtripTest {
@Test
public void pushPromiseFrameShouldMatch() throws Exception {
Http2Headers headers =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2").build();
Http2PushPromiseFrame in =
new DefaultHttp2PushPromiseFrame.Builder().setHeaders(headers)
@@ -224,7 +224,7 @@ public class Http2FrameRoundtripTest {
@Test
public void stressTest() throws Exception {
Http2Headers headers =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2").build();
String text = "hello world";
int numStreams = 1000;
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/HeaderBlockRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/HeaderBlockRoundtripTest.java
index 2e34a57ccc..f32ed6640d 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/HeaderBlockRoundtripTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/draft10/frame/HeaderBlockRoundtripTest.java
@@ -19,6 +19,7 @@ package io.netty.handler.codec.http2.draft10.frame;
import static org.junit.Assert.assertEquals;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http2.draft10.DefaultHttp2Headers;
import io.netty.handler.codec.http2.draft10.Http2Exception;
import io.netty.handler.codec.http2.draft10.Http2Headers;
import io.netty.handler.codec.http2.draft10.frame.decoder.DefaultHttp2HeadersDecoder;
@@ -52,33 +53,33 @@ public class HeaderBlockRoundtripTest {
@Test
public void roundtripShouldBeSuccessful() throws Http2Exception {
Http2Headers in =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2")
- .addHeader("accept", "image/png").addHeader("cache-control", "no-cache")
- .addHeader("custom", "value1").addHeader("custom", "value2")
- .addHeader("custom", "value3").addHeader("custom", "custom4").build();
+ .add("accept", "image/png").add("cache-control", "no-cache")
+ .add("custom", "value1").add("custom", "value2")
+ .add("custom", "value3").add("custom", "custom4").build();
assertRoundtripSuccessful(in);
}
@Test
public void successiveCallsShouldSucceed() throws Http2Exception {
Http2Headers in =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path")
- .addHeader("accept", "*/*").build();
+ .add("accept", "*/*").build();
assertRoundtripSuccessful(in);
in =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource1")
- .addHeader("accept", "image/jpeg").addHeader("cache-control", "no-cache")
+ .add("accept", "image/jpeg").add("cache-control", "no-cache")
.build();
assertRoundtripSuccessful(in);
in =
- new Http2Headers.Builder().setMethod("GET").setScheme("https")
+ new DefaultHttp2Headers.Builder().setMethod("GET").setScheme("https")
.setAuthority("example.org").setPath("/some/path/resource2")
- .addHeader("accept", "image/png").addHeader("cache-control", "no-cache")
+ .add("accept", "image/png").add("cache-control", "no-cache")
.build();
assertRoundtripSuccessful(in);
}