1 16 17 package org.springframework.web.multipart.commons; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.OutputStream ; 24 import java.io.UnsupportedEncodingException ; 25 import java.util.ArrayList ; 26 import java.util.Arrays ; 27 import java.util.Enumeration ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Set ; 32 33 import javax.servlet.FilterChain ; 34 import javax.servlet.ServletException ; 35 import javax.servlet.ServletRequest ; 36 import javax.servlet.ServletResponse ; 37 import javax.servlet.http.HttpServletRequest ; 38 import javax.servlet.http.HttpServletResponse ; 39 40 import junit.framework.TestCase; 41 import org.apache.commons.fileupload.DiskFileUpload; 42 import org.apache.commons.fileupload.FileItem; 43 44 import org.springframework.beans.MutablePropertyValues; 45 import org.springframework.mock.web.MockFilterConfig; 46 import org.springframework.mock.web.MockHttpServletRequest; 47 import org.springframework.mock.web.MockHttpServletResponse; 48 import org.springframework.mock.web.MockServletContext; 49 import org.springframework.web.bind.ServletRequestDataBinder; 50 import org.springframework.web.context.WebApplicationContext; 51 import org.springframework.web.context.support.StaticWebApplicationContext; 52 import org.springframework.web.multipart.MultipartException; 53 import org.springframework.web.multipart.MultipartFile; 54 import org.springframework.web.multipart.MultipartHttpServletRequest; 55 import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor; 56 import org.springframework.web.multipart.support.MultipartFilter; 57 import org.springframework.web.multipart.support.StringMultipartFileEditor; 58 import org.springframework.web.util.WebUtils; 59 60 64 public class CommonsMultipartResolverTests extends TestCase { 65 66 public void testWithApplicationContext() throws MultipartException, IOException { 67 StaticWebApplicationContext wac = new StaticWebApplicationContext(); 68 wac.setServletContext(new MockServletContext()); 69 wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File ("mytemp")); 70 wac.refresh(); 71 MockCommonsMultipartResolver resolver = new MockCommonsMultipartResolver(); 72 DiskFileUpload fileUpload = resolver.getFileUpload(); 73 resolver.setMaxUploadSize(1000); 74 resolver.setMaxInMemorySize(100); 75 resolver.setDefaultEncoding("enc"); 76 resolver.setServletContext(wac.getServletContext()); 77 assertEquals(1000, fileUpload.getSizeMax()); 78 assertEquals(100, fileUpload.getSizeThreshold()); 79 assertEquals("enc", fileUpload.getHeaderEncoding()); 80 assertTrue(fileUpload.getRepositoryPath().endsWith("mytemp")); 81 82 MockHttpServletRequest originalRequest = new MockHttpServletRequest(); 83 originalRequest.setContentType("multipart/form-data"); 84 originalRequest.addHeader("Content-type", "multipart/form-data"); 85 originalRequest.addParameter("getField", "getValue"); 86 assertTrue(resolver.isMultipart(originalRequest)); 87 MultipartHttpServletRequest request = resolver.resolveMultipart(originalRequest); 88 89 Set parameterNames = new HashSet (); 90 Enumeration parameterEnum = request.getParameterNames(); 91 while (parameterEnum.hasMoreElements()) { 92 parameterNames.add(parameterEnum.nextElement()); 93 } 94 assertEquals(3, parameterNames.size()); 95 assertTrue(parameterNames.contains("field3")); 96 assertTrue(parameterNames.contains("field4")); 97 assertTrue(parameterNames.contains("getField")); 98 assertEquals("value3", request.getParameter("field3")); 99 List parameterValues = Arrays.asList(request.getParameterValues("field3")); 100 assertEquals(1, parameterValues.size()); 101 assertTrue(parameterValues.contains("value3")); 102 assertEquals("value4", request.getParameter("field4")); 103 parameterValues = Arrays.asList(request.getParameterValues("field4")); 104 assertEquals(2, parameterValues.size()); 105 assertTrue(parameterValues.contains("value4")); 106 assertTrue(parameterValues.contains("value5")); 107 assertEquals("value4", request.getParameter("field4")); 108 assertEquals("getValue", request.getParameter("getField")); 109 110 List parameterMapKeys = new ArrayList (); 111 List parameterMapValues = new ArrayList (); 112 for (Iterator parameterMapIter = request.getParameterMap().keySet().iterator(); parameterMapIter.hasNext();) { 113 String key = (String ) parameterMapIter.next(); 114 parameterMapKeys.add(key); 115 parameterMapValues.add(request.getParameterMap().get(key)); 116 } 117 assertEquals(3, parameterMapKeys.size()); 118 assertEquals(3, parameterMapValues.size()); 119 int field3Index = parameterMapKeys.indexOf("field3"); 120 int field4Index = parameterMapKeys.indexOf("field4"); 121 int getFieldIndex = parameterMapKeys.indexOf("getField"); 122 assertTrue(field3Index != -1); 123 assertTrue(field4Index != -1); 124 assertTrue(getFieldIndex != -1); 125 parameterValues = Arrays.asList((String []) parameterMapValues.get(field3Index)); 126 assertEquals(1, parameterValues.size()); 127 assertTrue(parameterValues.contains("value3")); 128 parameterValues = Arrays.asList((String []) parameterMapValues.get(field4Index)); 129 assertEquals(2, parameterValues.size()); 130 assertTrue(parameterValues.contains("value4")); 131 assertTrue(parameterValues.contains("value5")); 132 parameterValues = Arrays.asList((String []) parameterMapValues.get(getFieldIndex)); 133 assertEquals(1, parameterValues.size()); 134 assertTrue(parameterValues.contains("getValue")); 135 136 Set fileNames = new HashSet (); 137 Iterator fileIter = request.getFileNames(); 138 while (fileIter.hasNext()) { 139 fileNames.add(fileIter.next()); 140 } 141 assertEquals(3, fileNames.size()); 142 assertTrue(fileNames.contains("field1")); 143 assertTrue(fileNames.contains("field2")); 144 assertTrue(fileNames.contains("field2x")); 145 CommonsMultipartFile file1 = (CommonsMultipartFile) request.getFile("field1"); 146 CommonsMultipartFile file2 = (CommonsMultipartFile) request.getFile("field2"); 147 CommonsMultipartFile file2x = (CommonsMultipartFile) request.getFile("field2x"); 148 List fileMapKeys = new ArrayList (); 149 List fileMapValues = new ArrayList (); 150 for (Iterator fileMapIter = request.getFileMap().keySet().iterator(); fileMapIter.hasNext();) { 151 String key = (String ) fileMapIter.next(); 152 fileMapKeys.add(key); 153 fileMapValues.add(request.getFileMap().get(key)); 154 } 155 assertEquals(3, fileMapKeys.size()); 156 assertEquals(3, fileMapValues.size()); 157 int field1Index = fileMapKeys.indexOf("field1"); 158 int field2Index = fileMapKeys.indexOf("field2"); 159 int field2xIndex = fileMapKeys.indexOf("field2x"); 160 assertTrue(field1Index != -1); 161 assertTrue(field2Index != -1); 162 assertTrue(field2xIndex != -1); 163 MultipartFile mapFile1 = (MultipartFile) fileMapValues.get(field1Index); 164 MultipartFile mapFile2 = (MultipartFile) fileMapValues.get(field2Index); 165 MultipartFile mapFile2x = (MultipartFile) fileMapValues.get(field2xIndex); 166 assertEquals(mapFile1, file1); 167 assertEquals(mapFile2, file2); 168 assertEquals(mapFile2x, file2x); 169 170 assertEquals("type1", file1.getContentType()); 171 assertEquals("type2", file2.getContentType()); 172 assertEquals("type2", file2x.getContentType()); 173 assertEquals("field1.txt", file1.getOriginalFilename()); 174 assertEquals("field2.txt", file2.getOriginalFilename()); 175 assertEquals("field2x.txt", file2x.getOriginalFilename()); 176 assertEquals("text1", new String (file1.getBytes())); 177 assertEquals("text2", new String (file2.getBytes())); 178 assertEquals(5, file1.getSize()); 179 assertEquals(5, file2.getSize()); 180 assertTrue(file1.getInputStream() instanceof ByteArrayInputStream ); 181 assertTrue(file2.getInputStream() instanceof ByteArrayInputStream ); 182 File transfer1 = new File ("C:/transfer1"); 183 File transfer2 = new File ("C:/transfer2"); 184 file1.transferTo(transfer1); 185 file2.transferTo(transfer2); 186 assertEquals(transfer1, ((MockFileItem) file1.getFileItem()).writtenFile); 187 assertEquals(transfer2, ((MockFileItem) file2.getFileItem()).writtenFile); 188 189 MultipartTestBean1 mtb1 = new MultipartTestBean1(); 190 assertEquals(null, mtb1.getField1()); 191 assertEquals(null, mtb1.getField2()); 192 ServletRequestDataBinder binder = new ServletRequestDataBinder(mtb1, "mybean"); 193 binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); 194 binder.bind(request); 195 assertEquals(file1, mtb1.getField1()); 196 assertEquals(new String (file2.getBytes()), new String (mtb1.getField2())); 197 198 MultipartTestBean2 mtb2 = new MultipartTestBean2(); 199 assertEquals(null, mtb2.getField1()); 200 assertEquals(null, mtb2.getField2()); 201 binder = new ServletRequestDataBinder(mtb2, "mybean"); 202 binder.registerCustomEditor(String .class, "field1", new StringMultipartFileEditor()); 203 binder.registerCustomEditor(String .class, "field2", new StringMultipartFileEditor("UTF-16")); 204 binder.bind(request); 205 assertEquals(new String (file1.getBytes()), mtb2.getField1()); 206 assertEquals(new String (file2.getBytes(), "UTF-16"), mtb2.getField2()); 207 208 resolver.cleanupMultipart(request); 209 assertTrue(((MockFileItem) file1.getFileItem()).deleted); 210 assertTrue(((MockFileItem) file2.getFileItem()).deleted); 211 212 resolver.setEmpty(true); 213 request = resolver.resolveMultipart(originalRequest); 214 binder.setBindEmptyMultipartFiles(false); 215 String firstBound = mtb2.getField1(); 216 binder.bind(request); 217 assertTrue(mtb2.getField1().length() > 0); 218 assertEquals(firstBound, mtb2.getField1()); 219 220 request = resolver.resolveMultipart(originalRequest); 221 binder.setBindEmptyMultipartFiles(true); 222 binder.bind(request); 223 assertTrue(mtb2.getField1().length() == 0); 224 } 225 226 public void testWithServletContextAndFilter() throws ServletException , IOException { 227 StaticWebApplicationContext wac = new StaticWebApplicationContext(); 228 wac.setServletContext(new MockServletContext()); 229 wac.registerSingleton("filterMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues()); 230 wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File ("mytemp")); 231 wac.refresh(); 232 wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); 233 CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext()); 234 assertTrue(resolver.getFileUpload().getRepositoryPath().endsWith("mytemp")); 235 236 MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter"); 237 filterConfig.addInitParameter("class", "notWritable"); 238 filterConfig.addInitParameter("unknownParam", "someValue"); 239 final MultipartFilter filter = new MultipartFilter(); 240 filter.init(filterConfig); 241 242 final List files = new ArrayList (); 243 final FilterChain filterChain = new FilterChain () { 244 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { 245 MultipartHttpServletRequest request = (MultipartHttpServletRequest) servletRequest; 246 files.addAll(request.getFileMap().values()); 247 } 248 }; 249 250 FilterChain filterChain2 = new FilterChain () { 251 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) 252 throws IOException , ServletException { 253 filter.doFilter(servletRequest, servletResponse, filterChain); 254 } 255 }; 256 257 MockHttpServletRequest originalRequest = new MockHttpServletRequest(); 258 MockHttpServletResponse response = new MockHttpServletResponse(); 259 originalRequest.setContentType("multipart/form-data"); 260 originalRequest.addHeader("Content-type", "multipart/form-data"); 261 filter.doFilter(originalRequest, response, filterChain2); 262 263 CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0); 264 CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1); 265 assertTrue(((MockFileItem) file1.getFileItem()).deleted); 266 assertTrue(((MockFileItem) file2.getFileItem()).deleted); 267 } 268 269 public void testWithServletContextAndFilterWithCustomBeanName() throws ServletException , IOException { 270 StaticWebApplicationContext wac = new StaticWebApplicationContext(); 271 wac.setServletContext(new MockServletContext()); 272 wac.refresh(); 273 wac.registerSingleton("myMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues()); 274 wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File ("mytemp")); 275 wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); 276 CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext()); 277 assertTrue(resolver.getFileUpload().getRepositoryPath().endsWith("mytemp")); 278 279 MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter"); 280 filterConfig.addInitParameter("multipartResolverBeanName", "myMultipartResolver"); 281 282 final List files = new ArrayList (); 283 FilterChain filterChain = new FilterChain () { 284 public void doFilter(ServletRequest originalRequest, ServletResponse response) { 285 if (originalRequest instanceof MultipartHttpServletRequest) { 286 MultipartHttpServletRequest request = (MultipartHttpServletRequest) originalRequest; 287 files.addAll(request.getFileMap().values()); 288 } 289 } 290 }; 291 292 MultipartFilter filter = new MultipartFilter() { 293 private boolean invoked = false; 294 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 295 FilterChain filterChain) throws ServletException , IOException { 296 super.doFilterInternal(request, response, filterChain); 297 if (invoked) { 298 throw new ServletException ("Should not have been invoked twice"); 299 } 300 invoked = true; 301 } 302 }; 303 filter.init(filterConfig); 304 305 MockHttpServletRequest originalRequest = new MockHttpServletRequest(); 306 originalRequest.setContentType("multipart/form-data"); 307 originalRequest.addHeader("Content-type", "multipart/form-data"); 308 HttpServletResponse response = new MockHttpServletResponse(); 309 filter.doFilter(originalRequest, response, filterChain); 310 filter.doFilter(originalRequest, response, filterChain); 311 CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0); 312 CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1); 313 assertTrue(((MockFileItem) file1.getFileItem()).deleted); 314 assertTrue(((MockFileItem) file2.getFileItem()).deleted); 315 } 316 317 318 public static class MockCommonsMultipartResolver extends CommonsMultipartResolver { 319 320 private boolean empty; 321 322 protected void setEmpty(boolean empty) { 323 this.empty = empty; 324 } 325 326 protected DiskFileUpload newFileUpload() { 327 return new DiskFileUpload() { 328 public List parseRequest(HttpServletRequest request) { 329 if (request instanceof MultipartHttpServletRequest) { 330 throw new IllegalStateException ("Already a multipart request"); 331 } 332 List fileItems = new ArrayList (); 333 MockFileItem fileItem1 = new MockFileItem( 334 "field1", "type1", empty ? "" : "field1.txt", empty ? "" : "text1"); 335 MockFileItem fileItem2 = new MockFileItem( 336 "field2", "type2", empty ? "" : "C:/field2.txt", empty ? "" : "text2"); 337 MockFileItem fileItem2x = new MockFileItem( 338 "field2x", "type2", empty ? "" : "C:\\field2x.txt", empty ? "" : "text2"); 339 MockFileItem fileItem3 = new MockFileItem("field3", null, null, "value3"); 340 MockFileItem fileItem4 = new MockFileItem("field4", null, null, "value4"); 341 MockFileItem fileItem5 = new MockFileItem("field4", null, null, "value5"); 342 fileItems.add(fileItem1); 343 fileItems.add(fileItem2); 344 fileItems.add(fileItem2x); 345 fileItems.add(fileItem3); 346 fileItems.add(fileItem4); 347 fileItems.add(fileItem5); 348 return fileItems; 349 } 350 }; 351 } 352 } 353 354 355 private static class MockFileItem implements FileItem { 356 357 private String fieldName; 358 private String contentType; 359 private String name; 360 private String value; 361 362 private File writtenFile; 363 private boolean deleted; 364 365 public MockFileItem(String fieldName, String contentType, String name, String value) { 366 this.fieldName = fieldName; 367 this.contentType = contentType; 368 this.name = name; 369 this.value = value; 370 } 371 372 public InputStream getInputStream() throws IOException { 373 return new ByteArrayInputStream (value.getBytes()); 374 } 375 376 public String getContentType() { 377 return contentType; 378 } 379 380 public String getName() { 381 return name; 382 } 383 384 public boolean isInMemory() { 385 return true; 386 } 387 388 public long getSize() { 389 return value.length(); 390 } 391 392 public byte[] get() { 393 return value.getBytes(); 394 } 395 396 public String getString(String encoding) throws UnsupportedEncodingException { 397 return new String (get(), encoding); 398 } 399 400 public String getString() { 401 return value; 402 } 403 404 public void write(File file) throws Exception { 405 this.writtenFile = file; 406 } 407 408 public File getWrittenFile() { 409 return writtenFile; 410 } 411 412 public void delete() { 413 this.deleted = true; 414 } 415 416 public boolean isDeleted() { 417 return deleted; 418 } 419 420 public String getFieldName() { 421 return fieldName; 422 } 423 424 public void setFieldName(String s) { 425 this.fieldName = s; 426 } 427 428 public boolean isFormField() { 429 return (this.name == null); 430 } 431 432 public void setFormField(boolean b) { 433 throw new UnsupportedOperationException (); 434 } 435 436 public OutputStream getOutputStream() throws IOException { 437 throw new UnsupportedOperationException (); 438 } 439 } 440 441 442 public class MultipartTestBean1 { 443 444 private MultipartFile field1; 445 private byte[] field2; 446 447 public void setField1(MultipartFile field1) { 448 this.field1 = field1; 449 } 450 451 public MultipartFile getField1() { 452 return field1; 453 } 454 455 public void setField2(byte[] field2) { 456 this.field2 = field2; 457 } 458 459 public byte[] getField2() { 460 return field2; 461 } 462 } 463 464 465 public class MultipartTestBean2 { 466 467 private String field1; 468 private String field2; 469 470 public void setField1(String field1) { 471 this.field1 = field1; 472 } 473 474 public String getField1() { 475 return field1; 476 } 477 478 public void setField2(String field2) { 479 this.field2 = field2; 480 } 481 482 public String getField2() { 483 return field2; 484 } 485 } 486 487 } 488 | Popular Tags |