28
28
import java .util .List ;
29
29
import java .util .Map ;
30
30
import java .util .Random ;
31
+ import javax .mail .internet .MimeUtility ;
31
32
32
33
import org .springframework .core .io .Resource ;
33
34
import org .springframework .http .HttpEntity ;
41
42
import org .springframework .util .StreamUtils ;
42
43
import org .springframework .util .StringUtils ;
43
44
44
- import javax .mail .internet .MimeUtility ;
45
-
46
45
/**
47
46
* Implementation of {@link HttpMessageConverter} to read and write 'normal' HTML
48
47
* forms and also to write (but not read) multipart data (e.g. file uploads).
79
78
* <p>Some methods in this class were inspired by {@code org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity}.
80
79
*
81
80
* @author Arjen Poutsma
82
- * @see MultiValueMap
81
+ * @author Rossen Stoyanchev
83
82
* @since 3.0
83
+ * @see MultiValueMap
84
84
*/
85
85
public class FormHttpMessageConverter implements HttpMessageConverter <MultiValueMap <String , ?>> {
86
86
@@ -128,6 +128,7 @@ public void setCharset(Charset charset) {
128
128
* and relies on {@code MimeUtility} from "javax.mail".
129
129
* <p>If not set file names will be encoded as US-ASCII.
130
130
* @param multipartCharset the charset to use
131
+ * @since 4.1.1
131
132
* @see <a href="http://en.wikipedia.org/wiki/MIME#Encoded-Word">Encoded-Word</a>
132
133
*/
133
134
public void setMultipartCharset (Charset multipartCharset ) {
@@ -150,7 +151,7 @@ public List<MediaType> getSupportedMediaTypes() {
150
151
* Set the message body converters to use. These converters are used to
151
152
* convert objects to MIME parts.
152
153
*/
153
- public final void setPartConverters (List <HttpMessageConverter <?>> partConverters ) {
154
+ public void setPartConverters (List <HttpMessageConverter <?>> partConverters ) {
154
155
Assert .notEmpty (partConverters , "'partConverters' must not be empty" );
155
156
this .partConverters = partConverters ;
156
157
}
@@ -159,8 +160,8 @@ public final void setPartConverters(List<HttpMessageConverter<?>> partConverters
159
160
* Add a message body converter. Such a converters is used to convert objects
160
161
* to MIME parts.
161
162
*/
162
- public final void addPartConverter (HttpMessageConverter <?> partConverter ) {
163
- Assert .notNull (partConverter , "'partConverter' must not be NULL " );
163
+ public void addPartConverter (HttpMessageConverter <?> partConverter ) {
164
+ Assert .notNull (partConverter , "'partConverter' must not be null " );
164
165
this .partConverters .add (partConverter );
165
166
}
166
167
@@ -174,9 +175,8 @@ public boolean canRead(Class<?> clazz, MediaType mediaType) {
174
175
return true ;
175
176
}
176
177
for (MediaType supportedMediaType : getSupportedMediaTypes ()) {
177
- // we can't read multipart
178
- if (!supportedMediaType .equals (MediaType .MULTIPART_FORM_DATA ) &&
179
- supportedMediaType .includes (mediaType )) {
178
+ // We can't read multipart....
179
+ if (!supportedMediaType .equals (MediaType .MULTIPART_FORM_DATA ) && supportedMediaType .includes (mediaType )) {
180
180
return true ;
181
181
}
182
182
}
@@ -204,13 +204,11 @@ public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String,
204
204
HttpInputMessage inputMessage ) throws IOException , HttpMessageNotReadableException {
205
205
206
206
MediaType contentType = inputMessage .getHeaders ().getContentType ();
207
- Charset charset = contentType .getCharSet () != null ? contentType .getCharSet () : this .charset ;
207
+ Charset charset = ( contentType .getCharSet () != null ? contentType .getCharSet () : this .charset ) ;
208
208
String body = StreamUtils .copyToString (inputMessage .getBody (), charset );
209
209
210
210
String [] pairs = StringUtils .tokenizeToStringArray (body , "&" );
211
-
212
211
MultiValueMap <String , String > result = new LinkedMultiValueMap <String , String >(pairs .length );
213
-
214
212
for (String pair : pairs ) {
215
213
int idx = pair .indexOf ('=' );
216
214
if (idx == -1 ) {
@@ -391,14 +389,8 @@ protected String getFilename(Object part) {
391
389
if (part instanceof Resource ) {
392
390
Resource resource = (Resource ) part ;
393
391
String filename = resource .getFilename ();
394
- if (multipartCharset != null ) {
395
- try {
396
- filename = MimeUtility .encodeText (filename , multipartCharset .name (), null );
397
- }
398
- catch (UnsupportedEncodingException e ) {
399
- // should not happen
400
- throw new IllegalStateException (e );
401
- }
392
+ if (this .multipartCharset != null ) {
393
+ filename = MimeDelegate .encode (filename , this .multipartCharset .name ());
402
394
}
403
395
return filename ;
404
396
}
@@ -414,25 +406,25 @@ protected String getFilename(Object part) {
414
406
*/
415
407
private class MultipartHttpOutputMessage implements HttpOutputMessage {
416
408
417
- private final HttpHeaders headers = new HttpHeaders () ;
409
+ private final OutputStream outputStream ;
418
410
419
- private final OutputStream os ;
411
+ private final HttpHeaders headers = new HttpHeaders () ;
420
412
421
413
private boolean headersWritten = false ;
422
414
423
- public MultipartHttpOutputMessage (OutputStream os ) {
424
- this .os = os ;
415
+ public MultipartHttpOutputMessage (OutputStream outputStream ) {
416
+ this .outputStream = outputStream ;
425
417
}
426
418
427
419
@ Override
428
420
public HttpHeaders getHeaders () {
429
- return headersWritten ? HttpHeaders .readOnlyHttpHeaders (headers ) : this .headers ;
421
+ return ( this . headersWritten ? HttpHeaders .readOnlyHttpHeaders (this . headers ) : this .headers ) ;
430
422
}
431
423
432
424
@ Override
433
425
public OutputStream getBody () throws IOException {
434
426
writeHeaders ();
435
- return this .os ;
427
+ return this .outputStream ;
436
428
}
437
429
438
430
private void writeHeaders () throws IOException {
@@ -441,14 +433,14 @@ private void writeHeaders() throws IOException {
441
433
byte [] headerName = getAsciiBytes (entry .getKey ());
442
434
for (String headerValueString : entry .getValue ()) {
443
435
byte [] headerValue = getAsciiBytes (headerValueString );
444
- os .write (headerName );
445
- os .write (':' );
446
- os .write (' ' );
447
- os .write (headerValue );
448
- writeNewLine (os );
436
+ this . outputStream .write (headerName );
437
+ this . outputStream .write (':' );
438
+ this . outputStream .write (' ' );
439
+ this . outputStream .write (headerValue );
440
+ writeNewLine (this . outputStream );
449
441
}
450
442
}
451
- writeNewLine (os );
443
+ writeNewLine (this . outputStream );
452
444
this .headersWritten = true ;
453
445
}
454
446
}
@@ -458,7 +450,23 @@ private byte[] getAsciiBytes(String name) {
458
450
return name .getBytes ("US-ASCII" );
459
451
}
460
452
catch (UnsupportedEncodingException ex ) {
461
- // should not happen, US-ASCII is always supported
453
+ // Should not happen - US-ASCII is always supported.
454
+ throw new IllegalStateException (ex );
455
+ }
456
+ }
457
+ }
458
+
459
+
460
+ /**
461
+ * Inner class to avoid a hard dependency on the JavaMail API.
462
+ */
463
+ private static class MimeDelegate {
464
+
465
+ public static String encode (String value , String charset ) {
466
+ try {
467
+ return MimeUtility .encodeText (value , charset , null );
468
+ }
469
+ catch (UnsupportedEncodingException ex ) {
462
470
throw new IllegalStateException (ex );
463
471
}
464
472
}
0 commit comments