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.handler.codec.http.HttpRequest;
19  import io.netty.util.internal.PlatformDependent;
20  
21  import java.io.IOException;
22  import java.nio.charset.Charset;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  
29  /**
30   * Default factory giving Attribute and FileUpload according to constructor
31   *
32   * Attribute and FileUpload could be :<br>
33   * - MemoryAttribute, DiskAttribute or MixedAttribute<br>
34   * - MemoryFileUpload, DiskFileUpload or MixedFileUpload<br>
35   * according to the constructor.
36   */
37  public class DefaultHttpDataFactory implements HttpDataFactory {
38      /**
39       * Proposed default MINSIZE as 16 KB.
40       */
41      public static final long MINSIZE = 0x4000;
42  
43      private final boolean useDisk;
44  
45      private final boolean checkSize;
46  
47      private long minSize;
48  
49      /**
50       * Keep all HttpDatas until cleanAllHttpDatas() is called.
51       */
52      private final Map<HttpRequest, List<HttpData>> requestFileDeleteMap = PlatformDependent.newConcurrentHashMap();
53  
54      /**
55       * HttpData will be in memory if less than default size (16KB).
56       * The type will be Mixed.
57       */
58      public DefaultHttpDataFactory() {
59          useDisk = false;
60          checkSize = true;
61          minSize = MINSIZE;
62      }
63  
64      /**
65       * HttpData will be always on Disk if useDisk is True, else always in Memory if False
66       */
67      public DefaultHttpDataFactory(boolean useDisk) {
68          this.useDisk = useDisk;
69          checkSize = false;
70      }
71  
72      /**
73       * HttpData will be on Disk if the size of the file is greater than minSize, else it
74       * will be in memory. The type will be Mixed.
75       */
76      public DefaultHttpDataFactory(long minSize) {
77          useDisk = false;
78          checkSize = true;
79          this.minSize = minSize;
80      }
81  
82      /**
83       * @return the associated list of Files for the request
84       */
85      private List<HttpData> getList(HttpRequest request) {
86          List<HttpData> list = requestFileDeleteMap.get(request);
87          if (list == null) {
88              list = new ArrayList<HttpData>();
89              requestFileDeleteMap.put(request, list);
90          }
91          return list;
92      }
93  
94      @Override
95      public Attribute createAttribute(HttpRequest request, String name) {
96          if (useDisk) {
97              Attribute attribute = new DiskAttribute(name);
98              List<HttpData> fileToDelete = getList(request);
99              fileToDelete.add(attribute);
100             return attribute;
101         }
102         if (checkSize) {
103             Attribute attribute = new MixedAttribute(name, minSize);
104             List<HttpData> fileToDelete = getList(request);
105             fileToDelete.add(attribute);
106             return attribute;
107         }
108         return new MemoryAttribute(name);
109     }
110 
111     @Override
112     public Attribute createAttribute(HttpRequest request, String name, String value) {
113         if (useDisk) {
114             Attribute attribute;
115             try {
116                 attribute = new DiskAttribute(name, value);
117             } catch (IOException e) {
118                 // revert to Mixed mode
119                 attribute = new MixedAttribute(name, value, minSize);
120             }
121             List<HttpData> fileToDelete = getList(request);
122             fileToDelete.add(attribute);
123             return attribute;
124         }
125         if (checkSize) {
126             Attribute attribute = new MixedAttribute(name, value, minSize);
127             List<HttpData> fileToDelete = getList(request);
128             fileToDelete.add(attribute);
129             return attribute;
130         }
131         try {
132             return new MemoryAttribute(name, value);
133         } catch (IOException e) {
134             throw new IllegalArgumentException(e);
135         }
136     }
137 
138     @Override
139     public FileUpload createFileUpload(HttpRequest request, String name, String filename,
140             String contentType, String contentTransferEncoding, Charset charset,
141             long size) {
142         if (useDisk) {
143             FileUpload fileUpload = new DiskFileUpload(name, filename, contentType,
144                     contentTransferEncoding, charset, size);
145             List<HttpData> fileToDelete = getList(request);
146             fileToDelete.add(fileUpload);
147             return fileUpload;
148         }
149         if (checkSize) {
150             FileUpload fileUpload = new MixedFileUpload(name, filename, contentType,
151                     contentTransferEncoding, charset, size, minSize);
152             List<HttpData> fileToDelete = getList(request);
153             fileToDelete.add(fileUpload);
154             return fileUpload;
155         }
156         return new MemoryFileUpload(name, filename, contentType,
157                 contentTransferEncoding, charset, size);
158     }
159 
160     @Override
161     public void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data) {
162         if (data instanceof HttpData) {
163             List<HttpData> fileToDelete = getList(request);
164             fileToDelete.remove(data);
165         }
166     }
167 
168     @Override
169     public void cleanRequestHttpDatas(HttpRequest request) {
170         List<HttpData> fileToDelete = requestFileDeleteMap.remove(request);
171         if (fileToDelete != null) {
172             for (HttpData data: fileToDelete) {
173                 data.delete();
174             }
175             fileToDelete.clear();
176         }
177     }
178 
179     @Override
180     public void cleanAllHttpDatas() {
181         Iterator<Entry<HttpRequest, List<HttpData>>> i = requestFileDeleteMap.entrySet().iterator();
182         while (i.hasNext()) {
183             Entry<HttpRequest, List<HttpData>> e = i.next();
184             i.remove();
185 
186             List<HttpData> fileToDelete = e.getValue();
187             if (fileToDelete != null) {
188                 for (HttpData data : fileToDelete) {
189                     data.delete();
190                 }
191                 fileToDelete.clear();
192             }
193         }
194     }
195 }