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    *   http://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.Unpooled;
20  import io.netty.util.IllegalReferenceCountException;
21  
22  import static io.netty.util.internal.ObjectUtil.checkNotNull;
23  
24  /**
25   * Default implementation of a {@link FullHttpResponse}.
26   */
27  public class DefaultFullHttpResponse extends DefaultHttpResponse implements FullHttpResponse {
28  
29      private final ByteBuf content;
30      private final HttpHeaders trailingHeaders;
31  
32      /**
33       * Used to cache the value of the hash code and avoid {@link IllegalReferenceCountException}.
34       */
35      private int hash;
36  
37      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status) {
38          this(version, status, Unpooled.buffer(0));
39      }
40  
41      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, ByteBuf content) {
42          this(version, status, content, true);
43      }
44  
45      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders) {
46          this(version, status, Unpooled.buffer(0), validateHeaders, false);
47      }
48  
49      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders,
50                                     boolean singleFieldHeaders) {
51          this(version, status, Unpooled.buffer(0), validateHeaders, singleFieldHeaders);
52      }
53  
54      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
55                                     ByteBuf content, boolean validateHeaders) {
56          this(version, status, content, validateHeaders, false);
57      }
58  
59      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
60                                     ByteBuf content, boolean validateHeaders, boolean singleFieldHeaders) {
61          super(version, status, validateHeaders, singleFieldHeaders);
62          this.content = checkNotNull(content, "content");
63          this.trailingHeaders = singleFieldHeaders ? new CombinedHttpHeaders(validateHeaders)
64                                                    : new DefaultHttpHeaders(validateHeaders);
65      }
66  
67      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
68              ByteBuf content, HttpHeaders headers, HttpHeaders trailingHeaders) {
69          super(version, status, headers);
70          this.content = checkNotNull(content, "content");
71          this.trailingHeaders = checkNotNull(trailingHeaders, "trailingHeaders");
72      }
73  
74      @Override
75      public HttpHeaders trailingHeaders() {
76          return trailingHeaders;
77      }
78  
79      @Override
80      public ByteBuf content() {
81          return content;
82      }
83  
84      @Override
85      public int refCnt() {
86          return content.refCnt();
87      }
88  
89      @Override
90      public FullHttpResponse retain() {
91          content.retain();
92          return this;
93      }
94  
95      @Override
96      public FullHttpResponse retain(int increment) {
97          content.retain(increment);
98          return this;
99      }
100 
101     @Override
102     public FullHttpResponse touch() {
103         content.touch();
104         return this;
105     }
106 
107     @Override
108     public FullHttpResponse touch(Object hint) {
109         content.touch(hint);
110         return this;
111     }
112 
113     @Override
114     public boolean release() {
115         return content.release();
116     }
117 
118     @Override
119     public boolean release(int decrement) {
120         return content.release(decrement);
121     }
122 
123     @Override
124     public FullHttpResponse setProtocolVersion(HttpVersion version) {
125         super.setProtocolVersion(version);
126         return this;
127     }
128 
129     @Override
130     public FullHttpResponse setStatus(HttpResponseStatus status) {
131         super.setStatus(status);
132         return this;
133     }
134 
135     @Override
136     public FullHttpResponse copy() {
137         return replace(content().copy());
138     }
139 
140     @Override
141     public FullHttpResponse duplicate() {
142         return replace(content().duplicate());
143     }
144 
145     @Override
146     public FullHttpResponse retainedDuplicate() {
147         return replace(content().retainedDuplicate());
148     }
149 
150     @Override
151     public FullHttpResponse replace(ByteBuf content) {
152         return new DefaultFullHttpResponse(protocolVersion(), status(), content, headers(), trailingHeaders());
153     }
154 
155     @Override
156     public int hashCode() {
157         int hash = this.hash;
158         if (hash == 0) {
159             if (content().refCnt() != 0) {
160                 try {
161                     hash = 31 + content().hashCode();
162                 } catch (IllegalReferenceCountException ignored) {
163                     // Handle race condition between checking refCnt() == 0 and using the object.
164                     hash = 31;
165                 }
166             } else {
167                 hash = 31;
168             }
169             hash = 31 * hash + trailingHeaders().hashCode();
170             hash = 31 * hash + super.hashCode();
171             this.hash = hash;
172         }
173         return hash;
174     }
175 
176     @Override
177     public boolean equals(Object o) {
178         if (!(o instanceof DefaultFullHttpResponse)) {
179             return false;
180         }
181 
182         DefaultFullHttpResponse other = (DefaultFullHttpResponse) o;
183 
184         return super.equals(other) &&
185                content().equals(other.content()) &&
186                trailingHeaders().equals(other.trailingHeaders());
187     }
188 
189     @Override
190     public String toString() {
191         return HttpMessageUtil.appendFullResponse(new StringBuilder(256), this).toString();
192     }
193 }