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