View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.http;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.buffer.ByteBufUtil;
20  import io.netty.buffer.Unpooled;
21  import io.netty.util.IllegalReferenceCountException;
22  import static io.netty.util.internal.ObjectUtil.checkNotNull;
23  
24  /**
25   * Default implementation of {@link FullHttpRequest}.
26   */
27  public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHttpRequest {
28      private final ByteBuf content;
29      private final HttpHeaders trailingHeader;
30  
31      /**
32       * Used to cache the value of the hash code and avoid {@link IllegalReferenceCountException}.
33       */
34      private int hash;
35  
36      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri) {
37          this(httpVersion, method, uri, Unpooled.buffer(0));
38      }
39  
40      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) {
41          this(httpVersion, method, uri, content, true);
42      }
43  
44      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, boolean validateHeaders) {
45          this(httpVersion, method, uri, Unpooled.buffer(0), validateHeaders);
46      }
47  
48      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
49                                    ByteBuf content, boolean validateHeaders) {
50          super(httpVersion, method, uri, validateHeaders);
51          this.content = checkNotNull(content, "content");
52          trailingHeader = new DefaultHttpHeaders(validateHeaders);
53      }
54  
55      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
56              ByteBuf content, HttpHeaders headers, HttpHeaders trailingHeader) {
57          super(httpVersion, method, uri, headers);
58          this.content = checkNotNull(content, "content");
59          this.trailingHeader = checkNotNull(trailingHeader, "trailingHeader");
60      }
61  
62      @Override
63      public HttpHeaders trailingHeaders() {
64          return trailingHeader;
65      }
66  
67      @Override
68      public ByteBuf content() {
69          return content;
70      }
71  
72      @Override
73      public int refCnt() {
74          return content.refCnt();
75      }
76  
77      @Override
78      public FullHttpRequest retain() {
79          content.retain();
80          return this;
81      }
82  
83      @Override
84      public FullHttpRequest retain(int increment) {
85          content.retain(increment);
86          return this;
87      }
88  
89      @Override
90      public FullHttpRequest touch() {
91          content.touch();
92          return this;
93      }
94  
95      @Override
96      public FullHttpRequest touch(Object hint) {
97          content.touch(hint);
98          return this;
99      }
100 
101     @Override
102     public boolean release() {
103         return content.release();
104     }
105 
106     @Override
107     public boolean release(int decrement) {
108         return content.release(decrement);
109     }
110 
111     @Override
112     public FullHttpRequest setProtocolVersion(HttpVersion version) {
113         super.setProtocolVersion(version);
114         return this;
115     }
116 
117     @Override
118     public FullHttpRequest setMethod(HttpMethod method) {
119         super.setMethod(method);
120         return this;
121     }
122 
123     @Override
124     public FullHttpRequest setUri(String uri) {
125         super.setUri(uri);
126         return this;
127     }
128 
129     @Override
130     public FullHttpRequest copy() {
131         return replace(content().copy());
132     }
133 
134     @Override
135     public FullHttpRequest duplicate() {
136         return replace(content().duplicate());
137     }
138 
139     @Override
140     public FullHttpRequest retainedDuplicate() {
141         return replace(content().retainedDuplicate());
142     }
143 
144     @Override
145     public FullHttpRequest replace(ByteBuf content) {
146         FullHttpRequest request = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content,
147                 headers().copy(), trailingHeaders().copy());
148         request.setDecoderResult(decoderResult());
149         return request;
150     }
151 
152     @Override
153     public int hashCode() {
154         int hash = this.hash;
155         if (hash == 0) {
156             if (ByteBufUtil.isAccessible(content())) {
157                 try {
158                     hash = 31 + content().hashCode();
159                 } catch (IllegalReferenceCountException ignored) {
160                     // Handle race condition between checking refCnt() == 0 and using the object.
161                     hash = 31;
162                 }
163             } else {
164                 hash = 31;
165             }
166             hash = 31 * hash + trailingHeaders().hashCode();
167             hash = 31 * hash + super.hashCode();
168             this.hash = hash;
169         }
170         return hash;
171     }
172 
173     @Override
174     public boolean equals(Object o) {
175         if (!(o instanceof DefaultFullHttpRequest)) {
176             return false;
177         }
178 
179         DefaultFullHttpRequest other = (DefaultFullHttpRequest) o;
180 
181         return super.equals(other) &&
182                content().equals(other.content()) &&
183                trailingHeaders().equals(other.trailingHeaders());
184     }
185 
186     @Override
187     public String toString() {
188         return HttpMessageUtil.appendFullRequest(new StringBuilder(256), this).toString();
189     }
190 }