View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.fileupload;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.OutputStream;
29  import java.util.Arrays;
30  import org.apache.commons.io.FileUtils;
31  
32  import org.junit.Test;
33  
34  /**
35   * Unit tests for {@link org.apache.commons.fileupload.DefaultFileItem}.
36   */
37  @SuppressWarnings({"deprecation", "javadoc"}) // unit tests for deprecated class
38  public class DefaultFileItemTest {
39  
40      /**
41       * Content type for regular form items.
42       */
43      private static final String textContentType = "text/plain";
44  
45      /**
46       * Content type for file uploads.
47       */
48      private static final String fileContentType = "application/octet-stream";
49  
50      /**
51       * Very low threshold for testing memory versus disk options.
52       */
53      private static final int threshold = 16;
54  
55      /**
56       * Test construction of a regular text field.
57       */
58      @Test
59      public void testTextFieldConstruction() {
60          FileItemFactory factory = createFactory(null);
61          String textFieldName = "textField";
62  
63          FileItem item = factory.createItem(
64                  textFieldName,
65                  textContentType,
66                  true,
67                  null
68          );
69          assertNotNull(item);
70          assertEquals(item.getFieldName(), textFieldName);
71          assertEquals(item.getContentType(), textContentType);
72          assertTrue(item.isFormField());
73          assertNull(item.getName());
74      }
75  
76      /**
77       * Test construction of a file field.
78       */
79      @Test
80      public void testFileFieldConstruction() {
81          FileItemFactory factory = createFactory(null);
82          String fileFieldName = "fileField";
83          String fileName = "originalFileName";
84  
85          FileItem item = factory.createItem(
86                  fileFieldName,
87                  fileContentType,
88                  false,
89                  fileName
90          );
91          assertNotNull(item);
92          assertEquals(item.getFieldName(), fileFieldName);
93          assertEquals(item.getContentType(), fileContentType);
94          assertFalse(item.isFormField());
95          assertEquals(item.getName(), fileName);
96      }
97  
98      /**
99       * Test creation of a field for which the amount of data falls below the
100      * configured threshold.
101      */
102     @Test
103     public void testBelowThreshold() {
104         FileItemFactory factory = createFactory(null);
105         String textFieldName = "textField";
106         String textFieldValue = "0123456789";
107         byte[] testFieldValueBytes = textFieldValue.getBytes();
108 
109         FileItem item = factory.createItem(
110                 textFieldName,
111                 textContentType,
112                 true,
113                 null
114         );
115         assertNotNull(item);
116 
117         try {
118             OutputStream os = item.getOutputStream();
119             os.write(testFieldValueBytes);
120             os.close();
121         } catch(IOException e) {
122             fail("Unexpected IOException");
123         }
124         assertTrue(item.isInMemory());
125         assertEquals(item.getSize(), testFieldValueBytes.length);
126         assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
127         assertEquals(item.getString(), textFieldValue);
128     }
129 
130     /**
131      * Test creation of a field for which the amount of data falls above the
132      * configured threshold, where no specific repository is configured.
133      */
134     @Test
135     public void testAboveThresholdDefaultRepository() {
136         doTestAboveThreshold(null);
137     }
138 
139     /**
140      * Test creation of a field for which the amount of data falls above the
141      * configured threshold, where a specific repository is configured.
142      */
143     @Test
144     public void testAboveThresholdSpecifiedRepository() throws IOException {
145         String tempPath = System.getProperty("java.io.tmpdir");
146         String tempDirName = "testAboveThresholdSpecifiedRepository";
147         File tempDir = new File(tempPath, tempDirName);
148         FileUtils.forceMkdir(tempDir);
149         doTestAboveThreshold(tempDir);
150         assertTrue(tempDir.delete());
151     }
152 
153     /**
154      * Common code for cases where the amount of data is above the configured
155      * threshold, but the ultimate destination of the data has not yet been
156      * determined.
157      *
158      * @param repository The directory within which temporary files will be
159      *                   created.
160      */
161     public void doTestAboveThreshold(File repository) {
162         FileItemFactory factory = createFactory(repository);
163         String textFieldName = "textField";
164         String textFieldValue = "01234567890123456789";
165         byte[] testFieldValueBytes = textFieldValue.getBytes();
166 
167         FileItem item = factory.createItem(
168                 textFieldName,
169                 textContentType,
170                 true,
171                 null
172         );
173         assertNotNull(item);
174 
175         try {
176             OutputStream os = item.getOutputStream();
177             os.write(testFieldValueBytes);
178             os.close();
179         } catch(IOException e) {
180             fail("Unexpected IOException");
181         }
182         assertFalse(item.isInMemory());
183         assertEquals(item.getSize(), testFieldValueBytes.length);
184         assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
185         assertEquals(item.getString(), textFieldValue);
186 
187         assertTrue(item instanceof DefaultFileItem);
188         DefaultFileItem dfi = (DefaultFileItem) item;
189         File storeLocation = dfi.getStoreLocation();
190         assertNotNull(storeLocation);
191         assertTrue(storeLocation.exists());
192         assertEquals(storeLocation.length(), testFieldValueBytes.length);
193 
194         if (repository != null) {
195             assertEquals(storeLocation.getParentFile(), repository);
196         }
197 
198         item.delete();
199     }
200 
201 
202     /**
203      * Creates a new <code>FileItemFactory</code> and returns it, obscuring
204      * from the caller the underlying implementation of this interface.
205      *
206      * @param repository The directory within which temporary files will be
207      *                   created.
208      * @return the new <code>FileItemFactory</code> instance.
209      */
210     protected FileItemFactory createFactory(File repository) {
211         return new DefaultFileItemFactory(threshold, repository);
212     }
213 
214     static final String CHARSET_ISO88591 = "ISO-8859-1";
215 
216     static final String CHARSET_ASCII = "US-ASCII";
217 
218     static final String CHARSET_UTF8 = "UTF-8";
219 
220     static final String CHARSET_KOI8_R = "KOI8_R";
221 
222     static final String CHARSET_WIN1251 = "Cp1251";
223 
224     static final int SWISS_GERMAN_STUFF_UNICODE [] = {
225         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
226     };
227 
228     static final int SWISS_GERMAN_STUFF_ISO8859_1 [] = {
229         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
230     };
231 
232     static final int SWISS_GERMAN_STUFF_UTF8 [] = {
233         0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4,
234         0x6D, 0xC3, 0xA4
235     };
236 
237     static final int RUSSIAN_STUFF_UNICODE [] = {
238         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
239         0x432, 0x435, 0x442
240     };
241 
242     static final int RUSSIAN_STUFF_UTF8 [] = {
243         0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F,
244         0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0,
245         0xB5, 0xD1, 0x82
246     };
247 
248     static final int RUSSIAN_STUFF_KOI8R [] = {
249         0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7,
250         0xC5, 0xD4
251     };
252 
253     static final int RUSSIAN_STUFF_WIN1251 [] = {
254         0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2,
255         0xE5, 0xF2
256     };
257 
258     private static String constructString(int[] unicodeChars) {
259         StringBuilder buffer = new StringBuilder();
260         if (unicodeChars != null) {
261             for (int unicodeChar : unicodeChars) {
262                 buffer.append((char) unicodeChar);
263             }
264         }
265         return buffer.toString();
266     }
267 
268     /**
269      * Test construction of content charset.
270      */
271     public void testContentCharSet() throws Exception {
272         FileItemFactory factory = createFactory(null);
273 
274         String teststr = constructString(SWISS_GERMAN_STUFF_UNICODE);
275 
276         FileItem item =
277             factory.createItem(
278                 "doesnotmatter",
279                 "text/plain; charset=" + CHARSET_ISO88591,
280                 true,
281                 null);
282         OutputStream outstream = item.getOutputStream();
283         for (int element : SWISS_GERMAN_STUFF_ISO8859_1) {
284             outstream.write(element);
285         }
286         outstream.close();
287         assertEquals(teststr, teststr, item.getString());
288 
289         item =
290             factory.createItem(
291                 "doesnotmatter",
292                 "text/plain; charset=" + CHARSET_UTF8,
293                 true,
294                 null);
295         outstream = item.getOutputStream();
296         for (int element : SWISS_GERMAN_STUFF_UTF8) {
297             outstream.write(element);
298         }
299         outstream.close();
300         assertEquals(teststr, teststr, item.getString());
301 
302         teststr = constructString(RUSSIAN_STUFF_UNICODE);
303 
304         item =
305             factory.createItem(
306                 "doesnotmatter",
307                 "text/plain; charset=" + CHARSET_KOI8_R,
308                 true,
309                 null);
310         outstream = item.getOutputStream();
311         for (int element : RUSSIAN_STUFF_KOI8R) {
312             outstream.write(element);
313         }
314         outstream.close();
315         assertEquals(teststr, teststr, item.getString());
316 
317         item =
318             factory.createItem(
319                 "doesnotmatter",
320                 "text/plain; charset=" + CHARSET_WIN1251,
321                 true,
322                 null);
323         outstream = item.getOutputStream();
324         for (int element : RUSSIAN_STUFF_WIN1251) {
325             outstream.write(element);
326         }
327         outstream.close();
328         assertEquals(teststr, teststr, item.getString());
329 
330         item =
331             factory.createItem(
332                 "doesnotmatter",
333                 "text/plain; charset=" + CHARSET_UTF8,
334                 true,
335                 null);
336         outstream = item.getOutputStream();
337         for (int element : RUSSIAN_STUFF_UTF8) {
338             outstream.write(element);
339         }
340         outstream.close();
341         assertEquals(teststr, teststr, item.getString());
342     }
343 
344 }