1
1
/*
2
- * Copyright 2002-2010 the original author or authors.
2
+ * Copyright 2002-2011 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.
66
66
* <p>This view resolver uses the requested {@linkplain MediaType media type} to select a suitable {@link View} for a
67
67
* request. This media type is determined by using the following criteria:
68
68
* <ol>
69
- * <li>If the requested path has a file extension and if the {@link #setFavorPathExtension(boolean) } property is
69
+ * <li>If the requested path has a file extension and if the {@link #setFavorPathExtension} property is
70
70
* {@code true}, the {@link #setMediaTypes(Map) mediaTypes} property is inspected for a matching media type.</li>
71
- * <li>If the request contains a parameter defining the extension and if the {@link #setFavorParameter(boolean) }
71
+ * <li>If the request contains a parameter defining the extension and if the {@link #setFavorParameter}
72
72
* property is <code>true</code>, the {@link #setMediaTypes(Map) mediaTypes} property is inspected for a matching
73
73
* media type. The default name of the parameter is <code>format</code> and it can be configured using the
74
74
* {@link #setParameterName(String) parameterName} property.</li>
75
75
* <li>If there is no match in the {@link #setMediaTypes(Map) mediaTypes} property and if the Java Activation
76
- * Framework (JAF) is both {@linkplain #setUseJaf(boolean) enabled} and present on the class path,
76
+ * Framework (JAF) is both {@linkplain #setUseJaf enabled} and present on the class path,
77
77
* {@link FileTypeMap#getContentType(String)} is used instead.</li>
78
78
* <li>If the previous steps did not result in a media type, and
79
- * {@link #setIgnoreAcceptHeader(boolean) ignoreAcceptHeader} is {@code false}, the request {@code Accept} header is
79
+ * {@link #setIgnoreAcceptHeader ignoreAcceptHeader} is {@code false}, the request {@code Accept} header is
80
80
* used.</li>
81
81
* </ol>
82
82
*
@@ -145,7 +145,7 @@ public int getOrder() {
145
145
}
146
146
147
147
/**
148
- * Indicates whether the extension of the request path should be used to determine the requested media type,
148
+ * Indicate whether the extension of the request path should be used to determine the requested media type,
149
149
* in favor of looking at the {@code Accept} header. The default value is {@code true}.
150
150
* <p>For instance, when this flag is <code>true</code> (the default), a request for {@code /hotels.pdf}
151
151
* will result in an {@code AbstractPdfView} being resolved, while the {@code Accept} header can be the
@@ -156,7 +156,7 @@ public void setFavorPathExtension(boolean favorPathExtension) {
156
156
}
157
157
158
158
/**
159
- * Indicates whether a request parameter should be used to determine the requested media type,
159
+ * Indicate whether a request parameter should be used to determine the requested media type,
160
160
* in favor of looking at the {@code Accept} header. The default value is {@code false}.
161
161
* <p>For instance, when this flag is <code>true</code>, a request for {@code /hotels?format=pdf} will result
162
162
* in an {@code AbstractPdfView} being resolved, while the {@code Accept} header can be the browser-defined
@@ -167,39 +167,38 @@ public void setFavorParameter(boolean favorParameter) {
167
167
}
168
168
169
169
/**
170
- * Sets the parameter name that can be used to determine the requested media type if the {@link
171
- * #setFavorParameter(boolean) } property is {@code true}. The default parameter name is {@code format}.
170
+ * Set the parameter name that can be used to determine the requested media type if the {@link
171
+ * #setFavorParameter} property is {@code true}. The default parameter name is {@code format}.
172
172
*/
173
173
public void setParameterName (String parameterName ) {
174
174
this .parameterName = parameterName ;
175
175
}
176
176
177
177
/**
178
- * Indicates whether the HTTP {@code Accept} header should be ignored. Default is {@code false}.
179
- * If set to {@code true}, this view resolver will only refer to the file extension and/or paramter,
180
- * as indicated by the {@link #setFavorPathExtension(boolean) favorPathExtension} and
181
- * {@link #setFavorParameter(boolean) favorParameter} properties.
178
+ * Indicate whether the HTTP {@code Accept} header should be ignored. Default is {@code false}.
179
+ * <p> If set to {@code true}, this view resolver will only refer to the file extension and/or
180
+ * parameter, as indicated by the {@link #setFavorPathExtension favorPathExtension} and
181
+ * {@link #setFavorParameter favorParameter} properties.
182
182
*/
183
183
public void setIgnoreAcceptHeader (boolean ignoreAcceptHeader ) {
184
184
this .ignoreAcceptHeader = ignoreAcceptHeader ;
185
185
}
186
186
187
187
/**
188
- * Indicates whether a {@link HttpServletResponse#SC_NOT_ACCEPTABLE 406 Not Acceptable} status code should be
189
- * returned if no suitable view can be found.
190
- *
188
+ * Indicate whether a {@link HttpServletResponse#SC_NOT_ACCEPTABLE 406 Not Acceptable}
189
+ * status code should be returned if no suitable view can be found.
191
190
* <p>Default is {@code false}, meaning that this view resolver returns {@code null} for
192
- * {@link #resolveViewName(String, Locale)} when an acceptable view cannot be found. This will allow for view
193
- * resolvers chaining. When this property is set to {@code true},
194
- * {@link #resolveViewName(String, Locale)} will respond with a view that sets the response status to
195
- * {@code 406 Not Acceptable} instead.
191
+ * {@link #resolveViewName(String, Locale)} when an acceptable view cannot be found.
192
+ * This will allow for view resolvers chaining. When this property is set to {@code true},
193
+ * {@link #resolveViewName(String, Locale)} will respond with a view that sets the
194
+ * response status to {@code 406 Not Acceptable} instead.
196
195
*/
197
196
public void setUseNotAcceptableStatusCode (boolean useNotAcceptableStatusCode ) {
198
197
this .useNotAcceptableStatusCode = useNotAcceptableStatusCode ;
199
198
}
200
199
201
200
/**
202
- * Sets the mapping from file extensions to media types.
201
+ * Set the mapping from file extensions to media types.
203
202
* <p>When this mapping is not set or when an extension is not present, this view resolver
204
203
* will fall back to using a {@link FileTypeMap} when the Java Action Framework is available.
205
204
*/
@@ -213,15 +212,15 @@ public void setMediaTypes(Map<String, String> mediaTypes) {
213
212
}
214
213
215
214
/**
216
- * Sets the default views to use when a more specific view can not be obtained
215
+ * Set the default views to use when a more specific view can not be obtained
217
216
* from the {@link ViewResolver} chain.
218
217
*/
219
218
public void setDefaultViews (List <View > defaultViews ) {
220
219
this .defaultViews = defaultViews ;
221
220
}
222
221
223
222
/**
224
- * Sets the default content type.
223
+ * Set the default content type.
225
224
* <p>This content type will be used when file extension, parameter, nor {@code Accept}
226
225
* header define a content-type, either through being disabled or empty.
227
226
*/
@@ -230,7 +229,7 @@ public void setDefaultContentType(MediaType defaultContentType) {
230
229
}
231
230
232
231
/**
233
- * Indicates whether to use the Java Activation Framework to map from file extensions to media types.
232
+ * Indicate whether to use the Java Activation Framework to map from file extensions to media types.
234
233
* <p>Default is {@code true}, i.e. the Java Activation Framework is used (if available).
235
234
*/
236
235
public void setUseJaf (boolean useJaf ) {
@@ -265,13 +264,38 @@ protected void initServletContext(ServletContext servletContext) {
265
264
OrderComparator .sort (this .viewResolvers );
266
265
}
267
266
267
+ public View resolveViewName (String viewName , Locale locale ) throws Exception {
268
+ RequestAttributes attrs = RequestContextHolder .getRequestAttributes ();
269
+ Assert .isInstanceOf (ServletRequestAttributes .class , attrs );
270
+ List <MediaType > requestedMediaTypes = getMediaTypes (((ServletRequestAttributes ) attrs ).getRequest ());
271
+ if (requestedMediaTypes != null ) {
272
+ List <View > candidateViews = getCandidateViews (viewName , locale , requestedMediaTypes );
273
+ View bestView = getBestView (candidateViews , requestedMediaTypes );
274
+ if (bestView != null ) {
275
+ return bestView ;
276
+ }
277
+ }
278
+ if (this .useNotAcceptableStatusCode ) {
279
+ if (logger .isDebugEnabled ()) {
280
+ logger .debug ("No acceptable view found; returning 406 (Not Acceptable) status code" );
281
+ }
282
+ return NOT_ACCEPTABLE_VIEW ;
283
+ }
284
+ else {
285
+ if (logger .isDebugEnabled ()) {
286
+ logger .debug ("No acceptable view found; returning null" );
287
+ }
288
+ return null ;
289
+ }
290
+ }
291
+
268
292
/**
269
293
* Determines the list of {@link MediaType} for the given {@link HttpServletRequest}.
270
294
* <p>The default implementation invokes {@link #getMediaTypeFromFilename(String)} if {@linkplain
271
- * #setFavorPathExtension(boolean) favorPathExtension} property is <code>true</code>. If the property is
272
- * <code>false</code>, or when a media type cannot be determined from the request path, this method will
273
- * inspect the {@code Accept} header of the request.
274
- * <p>This method can be overriden to provide a different algorithm.
295
+ * #setFavorPathExtension favorPathExtension} property is <code>true</code>. If the property is
296
+ * <code>false</code>, or when a media type cannot be determined from the request path,
297
+ * this method will inspect the {@code Accept} header of the request.
298
+ * <p>This method can be overridden to provide a different algorithm.
275
299
* @param request the current servlet request
276
300
* @return the list of media types requested, if any
277
301
*/
@@ -303,12 +327,20 @@ protected List<MediaType> getMediaTypes(HttpServletRequest request) {
303
327
if (!this .ignoreAcceptHeader ) {
304
328
String acceptHeader = request .getHeader (ACCEPT_HEADER );
305
329
if (StringUtils .hasText (acceptHeader )) {
306
- List <MediaType > mediaTypes = MediaType .parseMediaTypes (acceptHeader );
307
- MediaType .sortByQualityValue (mediaTypes );
308
- if (logger .isDebugEnabled ()) {
309
- logger .debug ("Requested media types are " + mediaTypes + " (based on Accept header)" );
330
+ try {
331
+ List <MediaType > mediaTypes = MediaType .parseMediaTypes (acceptHeader );
332
+ MediaType .sortByQualityValue (mediaTypes );
333
+ if (logger .isDebugEnabled ()) {
334
+ logger .debug ("Requested media types are " + mediaTypes + " (based on Accept header)" );
335
+ }
336
+ return mediaTypes ;
337
+ }
338
+ catch (IllegalArgumentException ex ) {
339
+ if (logger .isDebugEnabled ()) {
340
+ logger .debug ("Could not parse accept header [" + acceptHeader + "]: " + ex .getMessage ());
341
+ }
342
+ return null ;
310
343
}
311
- return mediaTypes ;
312
344
}
313
345
}
314
346
if (this .defaultContentType != null ) {
@@ -360,31 +392,6 @@ protected MediaType getMediaTypeFromParameter(String parameterValue) {
360
392
return this .mediaTypes .get (parameterValue .toLowerCase (Locale .ENGLISH ));
361
393
}
362
394
363
- public View resolveViewName (String viewName , Locale locale ) throws Exception {
364
- RequestAttributes attrs = RequestContextHolder .getRequestAttributes ();
365
- Assert .isInstanceOf (ServletRequestAttributes .class , attrs );
366
- List <MediaType > requestedMediaTypes = getMediaTypes (((ServletRequestAttributes ) attrs ).getRequest ());
367
- List <View > candidateViews = getCandidateViews (viewName , locale , requestedMediaTypes );
368
- View bestView = getBestView (candidateViews , requestedMediaTypes );
369
- if (bestView != null ) {
370
- return bestView ;
371
- }
372
- else {
373
- if (this .useNotAcceptableStatusCode ) {
374
- if (logger .isDebugEnabled ()) {
375
- logger .debug ("No acceptable view found; returning 406 (Not Acceptable) status code" );
376
- }
377
- return NOT_ACCEPTABLE_VIEW ;
378
- }
379
- else {
380
- if (logger .isDebugEnabled ()) {
381
- logger .debug ("No acceptable view found; returning null" );
382
- }
383
- return null ;
384
- }
385
- }
386
- }
387
-
388
395
private List <View > getCandidateViews (String viewName , Locale locale , List <MediaType > requestedMediaTypes )
389
396
throws Exception {
390
397
@@ -414,7 +421,7 @@ private List<View> getCandidateViews(String viewName, Locale locale, List<MediaT
414
421
415
422
private List <String > getExtensionsForMediaType (MediaType requestedMediaType ) {
416
423
List <String > result = new ArrayList <String >();
417
- for (Entry <String , MediaType > entry : mediaTypes .entrySet ()) {
424
+ for (Entry <String , MediaType > entry : this . mediaTypes .entrySet ()) {
418
425
if (requestedMediaType .includes (entry .getValue ())) {
419
426
result .add (entry .getKey ());
420
427
}
@@ -438,9 +445,8 @@ private View getBestView(List<View> candidateViews, List<MediaType> requestedMed
438
445
}
439
446
if (bestView != null ) {
440
447
if (logger .isDebugEnabled ()) {
441
- logger .debug (
442
- "Returning [" + bestView + "] based on requested media type '" + bestRequestedMediaType +
443
- "'" );
448
+ logger .debug ("Returning [" + bestView + "] based on requested media type '" +
449
+ bestRequestedMediaType + "'" );
444
450
}
445
451
break ;
446
452
}
@@ -495,7 +501,7 @@ private static FileTypeMap loadFileTypeMapFromContextSupportModule() {
495
501
496
502
public static MediaType getMediaType (String fileName ) {
497
503
String mediaType = fileTypeMap .getContentType (fileName );
498
- return StringUtils .hasText (mediaType ) ? MediaType .parseMediaType (mediaType ) : null ;
504
+ return ( StringUtils .hasText (mediaType ) ? MediaType .parseMediaType (mediaType ) : null ) ;
499
505
}
500
506
}
501
507
@@ -506,8 +512,7 @@ public String getContentType() {
506
512
return null ;
507
513
}
508
514
509
- public void render (Map <String , ?> model , HttpServletRequest request , HttpServletResponse response )
510
- throws Exception {
515
+ public void render (Map <String , ?> model , HttpServletRequest request , HttpServletResponse response ) {
511
516
response .setStatus (HttpServletResponse .SC_NOT_ACCEPTABLE );
512
517
}
513
518
};
0 commit comments