View Javadoc
1   /*
2    * Copyright 2012 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.multipart;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.handler.codec.http.HttpConstants;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.nio.charset.Charset;
25  
26  /**
27   * Mixed implementation using both in Memory and in File with a limit of size
28   */
29  public class MixedAttribute implements Attribute {
30      private Attribute attribute;
31  
32      private final long limitSize;
33      private long maxSize = DefaultHttpDataFactory.MAXSIZE;
34  
35      public MixedAttribute(String name, long limitSize) {
36          this(name, limitSize, HttpConstants.DEFAULT_CHARSET);
37      }
38  
39      public MixedAttribute(String name, long definedSize, long limitSize) {
40          this(name, definedSize, limitSize, HttpConstants.DEFAULT_CHARSET);
41      }
42  
43      public MixedAttribute(String name, long limitSize, Charset charset) {
44          this.limitSize = limitSize;
45          attribute = new MemoryAttribute(name, charset);
46      }
47  
48      public MixedAttribute(String name, long definedSize, long limitSize, Charset charset) {
49          this.limitSize = limitSize;
50          attribute = new MemoryAttribute(name, definedSize, charset);
51      }
52  
53      public MixedAttribute(String name, String value, long limitSize) {
54          this(name, value, limitSize, HttpConstants.DEFAULT_CHARSET);
55      }
56  
57      public MixedAttribute(String name, String value, long limitSize, Charset charset) {
58          this.limitSize = limitSize;
59          if (value.length() > this.limitSize) {
60              try {
61                  attribute = new DiskAttribute(name, value, charset);
62              } catch (IOException e) {
63                  // revert to Memory mode
64                  try {
65                      attribute = new MemoryAttribute(name, value, charset);
66                  } catch (IOException ignore) {
67                      throw new IllegalArgumentException(e);
68                  }
69              }
70          } else {
71              try {
72                  attribute = new MemoryAttribute(name, value, charset);
73              } catch (IOException e) {
74                  throw new IllegalArgumentException(e);
75              }
76          }
77      }
78  
79      @Override
80      public long getMaxSize() {
81          return maxSize;
82      }
83  
84      @Override
85      public void setMaxSize(long maxSize) {
86          this.maxSize = maxSize;
87          attribute.setMaxSize(maxSize);
88      }
89  
90      @Override
91      public void checkSize(long newSize) throws IOException {
92          if (maxSize >= 0 && newSize > maxSize) {
93              throw new IOException("Size exceed allowed maximum capacity");
94          }
95      }
96  
97      @Override
98      public void addContent(ByteBuf buffer, boolean last) throws IOException {
99          if (attribute instanceof MemoryAttribute) {
100             checkSize(attribute.length() + buffer.readableBytes());
101             if (attribute.length() + buffer.readableBytes() > limitSize) {
102                 DiskAttribute diskAttribute = new DiskAttribute(attribute
103                         .getName(), attribute.definedLength());
104                 diskAttribute.setMaxSize(maxSize);
105                 if (((MemoryAttribute) attribute).getByteBuf() != null) {
106                     diskAttribute.addContent(((MemoryAttribute) attribute)
107                         .getByteBuf(), false);
108                 }
109                 attribute = diskAttribute;
110             }
111         }
112         attribute.addContent(buffer, last);
113     }
114 
115     @Override
116     public void delete() {
117         attribute.delete();
118     }
119 
120     @Override
121     public byte[] get() throws IOException {
122         return attribute.get();
123     }
124 
125     @Override
126     public ByteBuf getByteBuf() throws IOException {
127         return attribute.getByteBuf();
128     }
129 
130     @Override
131     public Charset getCharset() {
132         return attribute.getCharset();
133     }
134 
135     @Override
136     public String getString() throws IOException {
137         return attribute.getString();
138     }
139 
140     @Override
141     public String getString(Charset encoding) throws IOException {
142         return attribute.getString(encoding);
143     }
144 
145     @Override
146     public boolean isCompleted() {
147         return attribute.isCompleted();
148     }
149 
150     @Override
151     public boolean isInMemory() {
152         return attribute.isInMemory();
153     }
154 
155     @Override
156     public long length() {
157         return attribute.length();
158     }
159 
160     @Override
161     public long definedLength() {
162         return attribute.definedLength();
163     }
164 
165     @Override
166     public boolean renameTo(File dest) throws IOException {
167         return attribute.renameTo(dest);
168     }
169 
170     @Override
171     public void setCharset(Charset charset) {
172         attribute.setCharset(charset);
173     }
174 
175     @Override
176     public void setContent(ByteBuf buffer) throws IOException {
177         checkSize(buffer.readableBytes());
178         if (buffer.readableBytes() > limitSize) {
179             if (attribute instanceof MemoryAttribute) {
180                 // change to Disk
181                 attribute = new DiskAttribute(attribute.getName(), attribute.definedLength());
182                 attribute.setMaxSize(maxSize);
183             }
184         }
185         attribute.setContent(buffer);
186     }
187 
188     @Override
189     public void setContent(File file) throws IOException {
190         checkSize(file.length());
191         if (file.length() > limitSize) {
192             if (attribute instanceof MemoryAttribute) {
193                 // change to Disk
194                 attribute = new DiskAttribute(attribute.getName(), attribute.definedLength());
195                 attribute.setMaxSize(maxSize);
196             }
197         }
198         attribute.setContent(file);
199     }
200 
201     @Override
202     public void setContent(InputStream inputStream) throws IOException {
203         if (attribute instanceof MemoryAttribute) {
204             // change to Disk even if we don't know the size
205             attribute = new DiskAttribute(attribute.getName(), attribute.definedLength());
206             attribute.setMaxSize(maxSize);
207         }
208         attribute.setContent(inputStream);
209     }
210 
211     @Override
212     public HttpDataType getHttpDataType() {
213         return attribute.getHttpDataType();
214     }
215 
216     @Override
217     public String getName() {
218         return attribute.getName();
219     }
220 
221     @Override
222     public int hashCode() {
223         return attribute.hashCode();
224     }
225 
226     @Override
227     public boolean equals(Object obj) {
228         return attribute.equals(obj);
229     }
230 
231     @Override
232     public int compareTo(InterfaceHttpData o) {
233         return attribute.compareTo(o);
234     }
235 
236     @Override
237     public String toString() {
238         return "Mixed: " + attribute;
239     }
240 
241     @Override
242     public String getValue() throws IOException {
243         return attribute.getValue();
244     }
245 
246     @Override
247     public void setValue(String value) throws IOException {
248         if (value != null) {
249             checkSize(value.getBytes().length);
250         }
251         attribute.setValue(value);
252     }
253 
254     @Override
255     public ByteBuf getChunk(int length) throws IOException {
256         return attribute.getChunk(length);
257     }
258 
259     @Override
260     public File getFile() throws IOException {
261         return attribute.getFile();
262     }
263 
264     @Override
265     public Attribute copy() {
266         return attribute.copy();
267     }
268 
269     @Override
270     public Attribute duplicate() {
271         return attribute.duplicate();
272     }
273 
274     @Override
275     public Attribute retainedDuplicate() {
276         return attribute.retainedDuplicate();
277     }
278 
279     @Override
280     public Attribute replace(ByteBuf content) {
281         return attribute.replace(content);
282     }
283 
284     @Override
285     public ByteBuf content() {
286         return attribute.content();
287     }
288 
289     @Override
290     public int refCnt() {
291         return attribute.refCnt();
292     }
293 
294     @Override
295     public Attribute retain() {
296         attribute.retain();
297         return this;
298     }
299 
300     @Override
301     public Attribute retain(int increment) {
302         attribute.retain(increment);
303         return this;
304     }
305 
306     @Override
307     public Attribute touch() {
308         attribute.touch();
309         return this;
310     }
311 
312     @Override
313     public Attribute touch(Object hint) {
314         attribute.touch(hint);
315         return this;
316     }
317 
318     @Override
319     public boolean release() {
320         return attribute.release();
321     }
322 
323     @Override
324     public boolean release(int decrement) {
325         return attribute.release(decrement);
326     }
327 }