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