1
1
/*
2
- * Copyright 2002-2016 the original author or authors.
2
+ * Copyright 2002-2017 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .test .web .servlet .htmlunit ;
18
18
19
19
import java .io .UnsupportedEncodingException ;
20
+ import java .lang .reflect .Method ;
20
21
import java .net .URL ;
21
22
import java .net .URLDecoder ;
23
+ import java .nio .charset .Charset ;
22
24
import java .util .ArrayList ;
23
25
import java .util .Enumeration ;
24
26
import java .util .List ;
50
52
import org .springframework .test .web .servlet .request .MockMvcRequestBuilders ;
51
53
import org .springframework .test .web .servlet .request .RequestPostProcessor ;
52
54
import org .springframework .util .Assert ;
55
+ import org .springframework .util .ClassUtils ;
53
56
import org .springframework .util .ObjectUtils ;
57
+ import org .springframework .util .ReflectionUtils ;
54
58
import org .springframework .util .StringUtils ;
55
59
import org .springframework .web .util .UriComponents ;
56
60
import org .springframework .web .util .UriComponentsBuilder ;
59
63
* Internal class used to transform a {@link WebRequest} into a
60
64
* {@link MockHttpServletRequest} using Spring MVC Test's {@link RequestBuilder}.
61
65
*
62
- * <p>By default the first path segment of the URL is used as the contextPath .
66
+ * <p>By default the first path segment of the URL is used as the context path .
63
67
* To override this default see {@link #setContextPath(String)}.
64
68
*
65
69
* @author Rob Winch
@@ -71,6 +75,11 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
71
75
72
76
private static final Pattern LOCALE_PATTERN = Pattern .compile ("^\\ s*(\\ w{2})(?:-(\\ w{2}))?(?:;q=(\\ d+\\ .\\ d+))?$" );
73
77
78
+ private static final Charset DEFAULT_CHARSET = Charset .forName ("ISO-8859-1" );
79
+
80
+
81
+ private static final Method getCharsetMethod = ClassUtils .getMethodIfAvailable (WebRequest .class , "getCharset" );
82
+
74
83
private final Map <String , MockHttpSession > sessions ;
75
84
76
85
private final WebClient webClient ;
@@ -98,23 +107,23 @@ public HtmlUnitRequestBuilder(Map<String, MockHttpSession> sessions, WebClient w
98
107
Assert .notNull (sessions , "Sessions Map must not be null" );
99
108
Assert .notNull (webClient , "WebClient must not be null" );
100
109
Assert .notNull (webRequest , "WebRequest must not be null" );
101
-
102
110
this .sessions = sessions ;
103
111
this .webClient = webClient ;
104
112
this .webRequest = webRequest ;
105
113
}
106
114
115
+
107
116
public MockHttpServletRequest buildRequest (ServletContext servletContext ) {
108
- String charset = getCharset ();
117
+ Charset charset = getCharset ();
109
118
String httpMethod = this .webRequest .getHttpMethod ().name ();
110
119
UriComponents uriComponents = uriComponents ();
111
120
112
121
MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest (
113
122
servletContext , httpMethod , uriComponents .getPath ());
114
123
parent (request , this .parentBuilder );
115
- request .setServerName (uriComponents .getHost ()); // needs to be first for additional headers
124
+ request .setServerName (uriComponents .getHost ()); // needs to be first for additional headers
116
125
authType (request );
117
- request .setCharacterEncoding (charset );
126
+ request .setCharacterEncoding (charset . name () );
118
127
content (request , charset );
119
128
contextPath (request , uriComponents );
120
129
contentType (request );
@@ -132,6 +141,21 @@ public MockHttpServletRequest buildRequest(ServletContext servletContext) {
132
141
return postProcess (request );
133
142
}
134
143
144
+ private Charset getCharset () {
145
+ if (getCharsetMethod != null ) {
146
+ Object value = ReflectionUtils .invokeMethod (getCharsetMethod , this .webRequest );
147
+ if (value instanceof Charset ) {
148
+ // HtmlUnit 2.25: a Charset
149
+ return (Charset ) value ;
150
+ }
151
+ else if (value != null ) {
152
+ // HtmlUnit up until 2.24: a String
153
+ return Charset .forName (value .toString ());
154
+ }
155
+ }
156
+ return DEFAULT_CHARSET ;
157
+ }
158
+
135
159
private MockHttpServletRequest postProcess (MockHttpServletRequest request ) {
136
160
if (this .parentPostProcessor != null ) {
137
161
request = this .parentPostProcessor .postProcessRequest (request );
@@ -220,17 +244,12 @@ private void authType(MockHttpServletRequest request) {
220
244
}
221
245
}
222
246
223
- private void content (MockHttpServletRequest request , String charset ) {
247
+ private void content (MockHttpServletRequest request , Charset charset ) {
224
248
String requestBody = this .webRequest .getRequestBody ();
225
249
if (requestBody == null ) {
226
250
return ;
227
251
}
228
- try {
229
- request .setContent (requestBody .getBytes (charset ));
230
- }
231
- catch (UnsupportedEncodingException ex ) {
232
- throw new IllegalStateException (ex );
233
- }
252
+ request .setContent (requestBody .getBytes (charset ));
234
253
}
235
254
236
255
private void contentType (MockHttpServletRequest request ) {
@@ -256,8 +275,8 @@ private void contextPath(MockHttpServletRequest request, UriComponents uriCompon
256
275
}
257
276
else {
258
277
if (!uriComponents .getPath ().startsWith (this .contextPath )) {
259
- throw new IllegalArgumentException (uriComponents .getPath () + " should start with contextPath " +
260
- this .contextPath );
278
+ throw new IllegalArgumentException (" \" " + uriComponents .getPath () +
279
+ " \" should start with context path \" " + this .contextPath + " \" " );
261
280
}
262
281
request .setContextPath (this .contextPath );
263
282
}
@@ -273,7 +292,7 @@ private void cookies(MockHttpServletRequest request) {
273
292
String cookieName = tokens .nextToken ().trim ();
274
293
if (!tokens .hasMoreTokens ()) {
275
294
throw new IllegalArgumentException ("Expected value for cookie name '" + cookieName +
276
- "'. Full cookie was " + cookieHeaderValue );
295
+ "': full cookie header was [ " + cookieHeaderValue + "]" );
277
296
}
278
297
String cookieValue = tokens .nextToken ().trim ();
279
298
processCookie (request , cookies , new Cookie (cookieName , cookieValue ));
@@ -305,14 +324,6 @@ private void processCookie(MockHttpServletRequest request, List<Cookie> cookies,
305
324
}
306
325
}
307
326
308
- private String getCharset () {
309
- String charset = this .webRequest .getCharset ();
310
- if (charset == null ) {
311
- return "ISO-8859-1" ;
312
- }
313
- return charset ;
314
- }
315
-
316
327
private String header (String headerName ) {
317
328
return this .webRequest .getAdditionalHeaders ().get (headerName );
318
329
}
@@ -394,7 +405,7 @@ private String urlDecode(String value) {
394
405
private Locale parseLocale (String locale ) {
395
406
Matcher matcher = LOCALE_PATTERN .matcher (locale );
396
407
if (!matcher .matches ()) {
397
- throw new IllegalArgumentException ("Invalid locale " + locale );
408
+ throw new IllegalArgumentException ("Invalid locale value [ " + locale + "]" );
398
409
}
399
410
String language = matcher .group (1 );
400
411
String country = matcher .group (2 );
0 commit comments