001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.fileupload; 018 019 import java.io.File; 020 import java.io.IOException; 021 import java.io.OutputStream; 022 import java.util.Arrays; 023 024 import junit.framework.TestCase; 025 import org.apache.commons.fileupload.DefaultFileItem; 026 import org.apache.commons.fileupload.DefaultFileItemFactory; 027 028 029 /** 030 * Unit tests for {@link org.apache.commons.fileupload.DefaultFileItem}. 031 * 032 * @author <a href="mailto:martinc@apache.org">Martin Cooper</a> 033 */ 034 public class DefaultFileItemTest extends TestCase 035 { 036 037 /** 038 * Content type for regular form items. 039 */ 040 private static final String textContentType = "text/plain"; 041 042 /** 043 * Content type for file uploads. 044 */ 045 private static final String fileContentType = "application/octet-stream"; 046 047 /** 048 * Very low threshold for testing memory versus disk options. 049 */ 050 private static final int threshold = 16; 051 052 /** 053 * Standard JUnit test case constructor. 054 * 055 * @param name The name of the test case. 056 */ 057 public DefaultFileItemTest(String name) 058 { 059 super(name); 060 } 061 062 /** 063 * Test construction of a regular text field. 064 */ 065 public void testTextFieldConstruction() 066 { 067 FileItemFactory factory = createFactory(null); 068 String textFieldName = "textField"; 069 070 FileItem item = factory.createItem( 071 textFieldName, 072 textContentType, 073 true, 074 null 075 ); 076 assertNotNull(item); 077 assertEquals(item.getFieldName(), textFieldName); 078 assertEquals(item.getContentType(), textContentType); 079 assertTrue(item.isFormField()); 080 assertNull(item.getName()); 081 } 082 083 /** 084 * Test construction of a file field. 085 */ 086 public void testFileFieldConstruction() 087 { 088 FileItemFactory factory = createFactory(null); 089 String fileFieldName = "fileField"; 090 String fileName = "originalFileName"; 091 092 FileItem item = factory.createItem( 093 fileFieldName, 094 fileContentType, 095 false, 096 fileName 097 ); 098 assertNotNull(item); 099 assertEquals(item.getFieldName(), fileFieldName); 100 assertEquals(item.getContentType(), fileContentType); 101 assertFalse(item.isFormField()); 102 assertEquals(item.getName(), fileName); 103 } 104 105 /** 106 * Test creation of a field for which the amount of data falls below the 107 * configured threshold. 108 */ 109 public void testBelowThreshold() 110 { 111 FileItemFactory factory = createFactory(null); 112 String textFieldName = "textField"; 113 String textFieldValue = "0123456789"; 114 byte[] testFieldValueBytes = textFieldValue.getBytes(); 115 116 FileItem item = factory.createItem( 117 textFieldName, 118 textContentType, 119 true, 120 null 121 ); 122 assertNotNull(item); 123 124 try 125 { 126 OutputStream os = item.getOutputStream(); 127 os.write(testFieldValueBytes); 128 os.close(); 129 } 130 catch(IOException e) 131 { 132 fail("Unexpected IOException"); 133 } 134 assertTrue(item.isInMemory()); 135 assertEquals(item.getSize(), testFieldValueBytes.length); 136 assertTrue(Arrays.equals(item.get(), testFieldValueBytes)); 137 assertEquals(item.getString(), textFieldValue); 138 } 139 140 /** 141 * Test creation of a field for which the amount of data falls above the 142 * configured threshold, where no specific repository is configured. 143 */ 144 public void testAboveThresholdDefaultRepository() 145 { 146 doTestAboveThreshold(null); 147 } 148 149 /** 150 * Test creation of a field for which the amount of data falls above the 151 * configured threshold, where a specific repository is configured. 152 */ 153 public void testAboveThresholdSpecifiedRepository() 154 { 155 String tempPath = System.getProperty("java.io.tmpdir"); 156 String tempDirName = "testAboveThresholdSpecifiedRepository"; 157 File tempDir = new File(tempPath, tempDirName); 158 tempDir.mkdir(); 159 doTestAboveThreshold(tempDir); 160 assertTrue(tempDir.delete()); 161 } 162 163 /** 164 * Common code for cases where the amount of data is above the configured 165 * threshold, but the ultimate destination of the data has not yet been 166 * determined. 167 * 168 * @param repository The directory within which temporary files will be 169 * created. 170 */ 171 public void doTestAboveThreshold(File repository) 172 { 173 FileItemFactory factory = createFactory(repository); 174 String textFieldName = "textField"; 175 String textFieldValue = "01234567890123456789"; 176 byte[] testFieldValueBytes = textFieldValue.getBytes(); 177 178 FileItem item = factory.createItem( 179 textFieldName, 180 textContentType, 181 true, 182 null 183 ); 184 assertNotNull(item); 185 186 try 187 { 188 OutputStream os = item.getOutputStream(); 189 os.write(testFieldValueBytes); 190 os.close(); 191 } 192 catch(IOException e) 193 { 194 fail("Unexpected IOException"); 195 } 196 assertFalse(item.isInMemory()); 197 assertEquals(item.getSize(), testFieldValueBytes.length); 198 assertTrue(Arrays.equals(item.get(), testFieldValueBytes)); 199 assertEquals(item.getString(), textFieldValue); 200 201 assertTrue(item instanceof DefaultFileItem); 202 DefaultFileItem dfi = (DefaultFileItem) item; 203 File storeLocation = dfi.getStoreLocation(); 204 assertNotNull(storeLocation); 205 assertTrue(storeLocation.exists()); 206 assertEquals(storeLocation.length(), testFieldValueBytes.length); 207 208 if (repository != null) 209 { 210 assertEquals(storeLocation.getParentFile(), repository); 211 } 212 213 item.delete(); 214 } 215 216 217 /** 218 * Creates a new <code>FileItemFactory</code> and returns it, obscuring 219 * from the caller the underlying implementation of this interface. 220 * 221 * @param repository The directory within which temporary files will be 222 * created. 223 * @return the new <code>FileItemFactory</code> instance. 224 */ 225 protected FileItemFactory createFactory(File repository) 226 { 227 return new DefaultFileItemFactory(threshold, repository); 228 } 229 230 231 static final String CHARSET_ISO88591 = "ISO-8859-1"; 232 static final String CHARSET_ASCII = "US-ASCII"; 233 static final String CHARSET_UTF8 = "UTF-8"; 234 static final String CHARSET_KOI8_R = "KOI8_R"; 235 static final String CHARSET_WIN1251 = "Cp1251"; 236 237 static final int SWISS_GERMAN_STUFF_UNICODE [] = 238 { 239 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4 240 }; 241 242 static final int SWISS_GERMAN_STUFF_ISO8859_1 [] = 243 { 244 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4 245 }; 246 247 static final int SWISS_GERMAN_STUFF_UTF8 [] = 248 { 249 0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4, 250 0x6D, 0xC3, 0xA4 251 }; 252 253 static final int RUSSIAN_STUFF_UNICODE [] = 254 { 255 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438, 256 0x432, 0x435, 0x442 257 }; 258 259 static final int RUSSIAN_STUFF_UTF8 [] = 260 { 261 0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F, 262 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 263 0xB5, 0xD1, 0x82 264 }; 265 266 static final int RUSSIAN_STUFF_KOI8R [] = 267 { 268 0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7, 269 0xC5, 0xD4 270 }; 271 272 static final int RUSSIAN_STUFF_WIN1251 [] = 273 { 274 0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2, 275 0xE5, 0xF2 276 }; 277 278 279 private static String constructString(int[] unicodeChars) 280 { 281 StringBuffer buffer = new StringBuffer(); 282 if (unicodeChars != null) 283 { 284 for (int i = 0; i < unicodeChars.length; i++) 285 { 286 buffer.append((char) unicodeChars[i]); 287 } 288 } 289 return buffer.toString(); 290 } 291 292 /** 293 * Test construction of content charset. 294 */ 295 public void testContentCharSet() throws Exception 296 { 297 FileItemFactory factory = createFactory(null); 298 299 String teststr = constructString(SWISS_GERMAN_STUFF_UNICODE); 300 301 FileItem item = 302 factory.createItem( 303 "doesnotmatter", 304 "text/plain; charset=" + CHARSET_ISO88591, 305 true, 306 null); 307 OutputStream outstream = item.getOutputStream(); 308 for (int i = 0; i < SWISS_GERMAN_STUFF_ISO8859_1.length; i++) 309 { 310 outstream.write(SWISS_GERMAN_STUFF_ISO8859_1[i]); 311 } 312 outstream.close(); 313 assertEquals(teststr, teststr, item.getString()); 314 315 item = 316 factory.createItem( 317 "doesnotmatter", 318 "text/plain; charset=" + CHARSET_UTF8, 319 true, 320 null); 321 outstream = item.getOutputStream(); 322 for (int i = 0; i < SWISS_GERMAN_STUFF_UTF8.length; i++) 323 { 324 outstream.write(SWISS_GERMAN_STUFF_UTF8[i]); 325 } 326 outstream.close(); 327 assertEquals(teststr, teststr, item.getString()); 328 329 teststr = constructString(RUSSIAN_STUFF_UNICODE); 330 331 item = 332 factory.createItem( 333 "doesnotmatter", 334 "text/plain; charset=" + CHARSET_KOI8_R, 335 true, 336 null); 337 outstream = item.getOutputStream(); 338 for (int i = 0; i < RUSSIAN_STUFF_KOI8R.length; i++) 339 { 340 outstream.write(RUSSIAN_STUFF_KOI8R[i]); 341 } 342 outstream.close(); 343 assertEquals(teststr, teststr, item.getString()); 344 345 item = 346 factory.createItem( 347 "doesnotmatter", 348 "text/plain; charset=" + CHARSET_WIN1251, 349 true, 350 null); 351 outstream = item.getOutputStream(); 352 for (int i = 0; i < RUSSIAN_STUFF_WIN1251.length; i++) 353 { 354 outstream.write(RUSSIAN_STUFF_WIN1251[i]); 355 } 356 outstream.close(); 357 assertEquals(teststr, teststr, item.getString()); 358 359 item = 360 factory.createItem( 361 "doesnotmatter", 362 "text/plain; charset=" + CHARSET_UTF8, 363 true, 364 null); 365 outstream = item.getOutputStream(); 366 for (int i = 0; i < RUSSIAN_STUFF_UTF8.length; i++) 367 { 368 outstream.write(RUSSIAN_STUFF_UTF8[i]); 369 } 370 outstream.close(); 371 assertEquals(teststr, teststr, item.getString()); 372 } 373 }