1
1
/*
2
- * Copyright 2002-2012 the original author or authors.
2
+ * Copyright 2002-2014 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.
18
18
19
19
import java .io .ByteArrayOutputStream ;
20
20
import java .util .Map ;
21
-
22
21
import javax .servlet .ServletException ;
23
22
import javax .servlet .http .HttpServletRequest ;
24
23
import javax .servlet .http .HttpServletResponse ;
25
24
import javax .xml .transform .stream .StreamResult ;
26
25
27
- import org .springframework .beans .BeansException ;
28
26
import org .springframework .oxm .Marshaller ;
29
27
import org .springframework .util .Assert ;
30
- import org .springframework .util .FileCopyUtils ;
28
+ import org .springframework .util .StreamUtils ;
29
+ import org .springframework .validation .BindingResult ;
31
30
import org .springframework .web .servlet .View ;
32
31
import org .springframework .web .servlet .view .AbstractView ;
33
32
34
33
/**
35
- * Spring-MVC {@link View} that allows for response context to be rendered as the result of marshalling by a {@link
36
- * Marshaller}.
34
+ * Spring-MVC {@link View} that allows for response context to be rendered as the result
35
+ * of marshalling by a {@link Marshaller}.
37
36
*
38
- * <p>The Object to be marshalled is supplied as a parameter in the model and then {@linkplain
39
- * #locateToBeMarshalled(Map) detected} during response rendering. Users can either specify a specific entry in the
40
- * model via the {@link #setModelKey(String) sourceKey} property or have Spring locate the Source object.
37
+ * <p>The Object to be marshalled is supplied as a parameter in the model and then
38
+ * {@linkplain #locateToBeMarshalled(Map) detected} during response rendering. Users can
39
+ * either specify a specific entry in the model via the {@link #setModelKey(String) sourceKey}
40
+ * property or have Spring locate the Source object.
41
41
*
42
42
* @author Arjen Poutsma
43
+ * @author Juergen Hoeller
43
44
* @since 3.0
44
45
*/
45
46
public class MarshallingView extends AbstractView {
@@ -49,13 +50,15 @@ public class MarshallingView extends AbstractView {
49
50
*/
50
51
public static final String DEFAULT_CONTENT_TYPE = "application/xml" ;
51
52
53
+
52
54
private Marshaller marshaller ;
53
55
54
56
private String modelKey ;
55
57
58
+
56
59
/**
57
- * Constructs a new {@code MarshallingView} with no {@link Marshaller} set. The marshaller must be set after
58
- * construction by invoking {@link #setMarshaller(Marshaller) }.
60
+ * Constructs a new {@code MarshallingView} with no {@link Marshaller} set.
61
+ * The marshaller must be set after construction by invoking {@link #setMarshaller}.
59
62
*/
60
63
public MarshallingView () {
61
64
setContentType (DEFAULT_CONTENT_TYPE );
@@ -66,80 +69,81 @@ public MarshallingView() {
66
69
* Constructs a new {@code MarshallingView} with the given {@link Marshaller} set.
67
70
*/
68
71
public MarshallingView (Marshaller marshaller ) {
69
- Assert . notNull ( marshaller , "'marshaller' must not be null" );
70
- setContentType ( DEFAULT_CONTENT_TYPE );
72
+ this ( );
73
+ Assert . notNull ( marshaller , "Marshaller must not be null" );
71
74
this .marshaller = marshaller ;
72
- setExposePathVariables (false );
73
75
}
74
76
77
+
75
78
/**
76
79
* Sets the {@link Marshaller} to be used by this view.
77
80
*/
78
81
public void setMarshaller (Marshaller marshaller ) {
79
- Assert .notNull (marshaller , "'marshaller' must not be null" );
80
82
this .marshaller = marshaller ;
81
83
}
82
84
83
85
/**
84
- * Set the name of the model key that represents the object to be marshalled. If not specified, the model map will be
85
- * searched for a supported value type.
86
- *
86
+ * Set the name of the model key that represents the object to be marshalled.
87
+ * If not specified, the model map will be searched for a supported value type.
87
88
* @see Marshaller#supports(Class)
88
89
*/
89
90
public void setModelKey (String modelKey ) {
90
91
this .modelKey = modelKey ;
91
92
}
92
93
93
94
@ Override
94
- protected void initApplicationContext () throws BeansException {
95
- Assert .notNull (marshaller , "Property 'marshaller' is required" );
95
+ protected void initApplicationContext () {
96
+ Assert .notNull (this . marshaller , "Property 'marshaller' is required" );
96
97
}
97
98
99
+
98
100
@ Override
99
- protected void renderMergedOutputModel (Map <String , Object > model ,
100
- HttpServletRequest request ,
101
- HttpServletResponse response ) throws Exception {
101
+ protected void renderMergedOutputModel (Map <String , Object > model , HttpServletRequest request ,
102
+ HttpServletResponse response ) throws Exception {
103
+
102
104
Object toBeMarshalled = locateToBeMarshalled (model );
103
105
if (toBeMarshalled == null ) {
104
106
throw new ServletException ("Unable to locate object to be marshalled in model: " + model );
105
107
}
106
108
ByteArrayOutputStream bos = new ByteArrayOutputStream (2048 );
107
- marshaller .marshal (toBeMarshalled , new StreamResult (bos ));
109
+ this . marshaller .marshal (toBeMarshalled , new StreamResult (bos ));
108
110
109
111
setResponseContentType (request , response );
110
112
response .setContentLength (bos .size ());
111
113
112
- FileCopyUtils .copy (bos .toByteArray (), response .getOutputStream ());
114
+ StreamUtils .copy (bos .toByteArray (), response .getOutputStream ());
113
115
}
114
116
115
117
/**
116
- * Locates the object to be marshalled. The default implementation first attempts to look under the configured
117
- * {@linkplain #setModelKey(String) model key}, if any, before attempting to locate an object of {@linkplain
118
- * Marshaller#supports(Class) supported type}.
119
- *
118
+ * Locate the object to be marshalled.
119
+ * <p>The default implementation first attempts to look under the configured
120
+ * {@linkplain #setModelKey(String) model key}, if any, before attempting to
121
+ * locate an object of {@linkplain Marshaller#supports(Class) supported type}.
120
122
* @param model the model Map
121
123
* @return the Object to be marshalled (or {@code null} if none found)
122
- * @throws ServletException if the model object specified by the {@linkplain #setModelKey(String) model key} is not
123
- * supported by the marshaller
124
+ * @throws ServletException if the model object specified by the
125
+ * {@linkplain #setModelKey(String) model key} is not supported by the marshaller
124
126
* @see #setModelKey(String)
125
127
*/
126
128
protected Object locateToBeMarshalled (Map <String , Object > model ) throws ServletException {
127
129
if (this .modelKey != null ) {
128
- Object o = model .get (this .modelKey );
129
- if (o == null ) {
130
- throw new ServletException ("Model contains no object with key [" + modelKey + "]" );
130
+ Object obj = model .get (this .modelKey );
131
+ if (obj == null ) {
132
+ throw new ServletException ("Model contains no object with key [" + this . modelKey + "]" );
131
133
}
132
- if (!this .marshaller .supports (o .getClass ())) {
133
- throw new ServletException ("Model object [" + o + "] retrieved via key [" + modelKey +
134
- "] is not supported by the Marshaller" );
134
+ if (!this .marshaller .supports (obj .getClass ())) {
135
+ throw new ServletException ("Model object [" + obj + "] retrieved via key [" +
136
+ this . modelKey + "] is not supported by the Marshaller" );
135
137
}
136
- return o ;
138
+ return obj ;
137
139
}
138
- for (Object o : model .values ()) {
139
- if (o != null && this .marshaller .supports (o .getClass ())) {
140
- return o ;
140
+ for (Object obj : model .values ()) {
141
+ if (obj != null && (model .size () == 1 || !(obj instanceof BindingResult )) &&
142
+ this .marshaller .supports (obj .getClass ())) {
143
+ return obj ;
141
144
}
142
145
}
143
146
return null ;
144
147
}
148
+
145
149
}
0 commit comments