1616
1717package org .springframework .oxm .jaxb ;
1818
19- import java .io .ByteArrayInputStream ;
20- import java .io .IOException ;
21- import java .io .InputStream ;
22- import java .io .OutputStream ;
23- import java .io .UnsupportedEncodingException ;
24- import java .lang .reflect .ParameterizedType ;
25- import java .lang .reflect .Type ;
26- import java .net .URI ;
27- import java .net .URISyntaxException ;
28- import java .net .URLDecoder ;
29- import java .net .URLEncoder ;
30- import java .util .Arrays ;
31- import java .util .Map ;
32- import java .util .UUID ;
19+ import org .springframework .core .io .Resource ;
20+ import org .springframework .oxm .GenericMarshaller ;
21+ import org .springframework .oxm .GenericUnmarshaller ;
22+ import org .springframework .oxm .XmlMappingException ;
23+ import org .springframework .oxm .mime .MimeContainer ;
24+ import org .springframework .oxm .mime .MimeMarshaller ;
25+ import org .springframework .oxm .mime .MimeUnmarshaller ;
26+ import org .springframework .util .*;
27+ import org .springframework .xml .transform .StaxResult ;
28+ import org .springframework .xml .transform .StaxSource ;
29+ import org .springframework .xml .validation .SchemaLoaderUtils ;
30+
3331import javax .activation .DataHandler ;
3432import javax .activation .DataSource ;
3533import javax .xml .XMLConstants ;
36- import javax .xml .bind .JAXBContext ;
37- import javax .xml .bind .JAXBElement ;
38- import javax .xml .bind .JAXBException ;
39- import javax .xml .bind .Marshaller ;
40- import javax .xml .bind .Unmarshaller ;
34+ import javax .xml .bind .*;
4135import javax .xml .bind .annotation .XmlRootElement ;
4236import javax .xml .bind .annotation .XmlType ;
4337import javax .xml .bind .annotation .adapters .XmlAdapter ;
4438import javax .xml .bind .attachment .AttachmentMarshaller ;
4539import javax .xml .bind .attachment .AttachmentUnmarshaller ;
40+ import javax .xml .datatype .Duration ;
41+ import javax .xml .datatype .XMLGregorianCalendar ;
42+ import javax .xml .namespace .QName ;
4643import javax .xml .transform .Result ;
4744import javax .xml .transform .Source ;
4845import javax .xml .validation .Schema ;
49-
50- import org .springframework .core .io .Resource ;
51- import org .springframework .oxm .GenericMarshaller ;
52- import org .springframework .oxm .GenericUnmarshaller ;
53- import org .springframework .oxm .XmlMappingException ;
54- import org .springframework .oxm .mime .MimeContainer ;
55- import org .springframework .oxm .mime .MimeMarshaller ;
56- import org .springframework .oxm .mime .MimeUnmarshaller ;
57- import org .springframework .util .ClassUtils ;
58- import org .springframework .util .FileCopyUtils ;
59- import org .springframework .util .ObjectUtils ;
60- import org .springframework .util .StringUtils ;
61- import org .springframework .xml .transform .StaxResult ;
62- import org .springframework .xml .transform .StaxSource ;
63- import org .springframework .xml .validation .SchemaLoaderUtils ;
46+ import java .awt .*;
47+ import java .io .*;
48+ import java .lang .reflect .GenericArrayType ;
49+ import java .lang .reflect .ParameterizedType ;
50+ import java .lang .reflect .Type ;
51+ import java .math .BigDecimal ;
52+ import java .math .BigInteger ;
53+ import java .net .URI ;
54+ import java .net .URISyntaxException ;
55+ import java .net .URLDecoder ;
56+ import java .net .URLEncoder ;
57+ import java .util .*;
6458
6559/**
6660 * Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
@@ -129,7 +123,9 @@ public void setJaxbContextProperties(Map<String, ?> jaxbContextProperties) {
129123 this .jaxbContextProperties = jaxbContextProperties ;
130124 }
131125
132- /** Sets the <code>Marshaller.Listener</code> to be registered with the JAXB <code>Marshaller</code>. */
126+ /**
127+ * Sets the <code>Marshaller.Listener</code> to be registered with the JAXB <code>Marshaller</code>.
128+ */
133129 public void setMarshallerListener (Marshaller .Listener marshallerListener ) {
134130 this .marshallerListener = marshallerListener ;
135131 }
@@ -152,45 +148,82 @@ public void setSchemaLanguage(String schemaLanguage) {
152148 this .schemaLanguage = schemaLanguage ;
153149 }
154150
155- /** Sets the schema resource to use for validation. */
151+ /**
152+ * Sets the schema resource to use for validation.
153+ */
156154 public void setSchema (Resource schemaResource ) {
157155 schemaResources = new Resource []{schemaResource };
158156 }
159157
160- /** Sets the schema resources to use for validation. */
158+ /**
159+ * Sets the schema resources to use for validation.
160+ */
161161 public void setSchemas (Resource [] schemaResources ) {
162162 this .schemaResources = schemaResources ;
163163 }
164164
165- /** Sets the <code>Unmarshaller.Listener</code> to be registered with the JAXB <code>Unmarshaller</code>. */
165+ /**
166+ * Sets the <code>Unmarshaller.Listener</code> to be registered with the JAXB <code>Unmarshaller</code>.
167+ */
166168 public void setUnmarshallerListener (Unmarshaller .Listener unmarshallerListener ) {
167169 this .unmarshallerListener = unmarshallerListener ;
168170 }
169171
170172 public boolean supports (Type type ) {
171173 if (type instanceof Class ) {
172174 return supportsInternal ((Class ) type , true );
173- }
174- else if (type instanceof ParameterizedType ) {
175+ } else if (type instanceof ParameterizedType ) {
175176 ParameterizedType parameterizedType = (ParameterizedType ) type ;
176177 if (JAXBElement .class .equals (parameterizedType .getRawType ())) {
177- Type [] typeArguments = parameterizedType .getActualTypeArguments ();
178- for (int i = 0 ; i < typeArguments .length ; i ++) {
179- if (typeArguments [i ] instanceof Class ) {
180- if (!supportsInternal ((Class ) typeArguments [i ], false )) {
181- return false ;
182- }
183- }
184- else if (!supports (typeArguments [i ])) {
178+ Assert .isTrue (parameterizedType .getActualTypeArguments ().length == 1 ,
179+ "Invalid amount of parameterized types in JAXBElement" );
180+ Type typeArgument = parameterizedType .getActualTypeArguments ()[0 ];
181+ if (typeArgument instanceof Class ) {
182+ Class clazz = (Class ) typeArgument ;
183+ if (!isPrimitiveType (clazz ) && !isStandardType (clazz ) && !supportsInternal (clazz , false )) {
185184 return false ;
186185 }
187186 }
187+ else if (typeArgument instanceof GenericArrayType ) {
188+ GenericArrayType genericArrayType = (GenericArrayType ) typeArgument ;
189+ return genericArrayType .getGenericComponentType ().equals (Byte .TYPE );
190+ } else if (!supports (typeArgument )) {
191+ return false ;
192+ }
188193 return true ;
189194 }
190195 }
191196 return false ;
192197 }
193198
199+ private boolean isPrimitiveType (Class clazz ) {
200+ return (Boolean .class .equals (clazz ) ||
201+ Byte .class .equals (clazz ) ||
202+ Short .class .equals (clazz ) ||
203+ Integer .class .equals (clazz ) ||
204+ Long .class .equals (clazz ) ||
205+ Float .class .equals (clazz ) ||
206+ Double .class .equals (clazz ) ||
207+ byte [].class .equals (clazz ));
208+ }
209+
210+ private boolean isStandardType (Class clazz ) {
211+ return (String .class .equals (clazz ) ||
212+ BigInteger .class .equals (clazz ) ||
213+ BigDecimal .class .equals (clazz ) ||
214+ Calendar .class .isAssignableFrom (clazz ) ||
215+ Date .class .isAssignableFrom (clazz ) ||
216+ QName .class .equals (clazz ) ||
217+ URI .class .equals (clazz ) ||
218+ XMLGregorianCalendar .class .isAssignableFrom (clazz ) ||
219+ Duration .class .isAssignableFrom (clazz ) ||
220+ Object .class .equals (clazz ) ||
221+ Image .class .isAssignableFrom (clazz ) ||
222+ DataHandler .class .equals (clazz ) ||
223+ Source .class .isAssignableFrom (clazz ) ||
224+ UUID .class .equals (clazz ));
225+ }
226+
194227 public boolean supports (Class clazz ) {
195228 return supportsInternal (clazz , true );
196229 }
@@ -216,8 +249,7 @@ private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement)
216249 }
217250 }
218251 return false ;
219- }
220- else if (!ObjectUtils .isEmpty (classesToBeBound )) {
252+ } else if (!ObjectUtils .isEmpty (classesToBeBound )) {
221253 return Arrays .asList (classesToBeBound ).contains (clazz );
222254 }
223255 return false ;
@@ -244,11 +276,9 @@ protected JAXBContext createJaxbContext() throws Exception {
244276 }
245277 if (StringUtils .hasLength (getContextPath ())) {
246278 return createJaxbContextFromContextPath ();
247- }
248- else if (!ObjectUtils .isEmpty (classesToBeBound )) {
279+ } else if (!ObjectUtils .isEmpty (classesToBeBound )) {
249280 return createJaxbContextFromClasses ();
250- }
251- else {
281+ } else {
252282 throw new IllegalArgumentException ("setting either contextPath or classesToBeBound is required" );
253283 }
254284 }
@@ -260,8 +290,7 @@ private JAXBContext createJaxbContextFromContextPath() throws JAXBException {
260290 if (jaxbContextProperties != null ) {
261291 return JAXBContext
262292 .newInstance (getContextPath (), ClassUtils .getDefaultClassLoader (), jaxbContextProperties );
263- }
264- else {
293+ } else {
265294 return JAXBContext .newInstance (getContextPath ());
266295 }
267296 }
@@ -273,8 +302,7 @@ private JAXBContext createJaxbContextFromClasses() throws JAXBException {
273302 }
274303 if (jaxbContextProperties != null ) {
275304 return JAXBContext .newInstance (classesToBeBound , jaxbContextProperties );
276- }
277- else {
305+ } else {
278306 return JAXBContext .newInstance (classesToBeBound );
279307 }
280308 }
@@ -327,8 +355,7 @@ public void marshal(Object graph, Result result, MimeContainer mimeContainer) th
327355 }
328356 if (result instanceof StaxResult ) {
329357 marshalStaxResult (marshaller , graph , (StaxResult ) result );
330- }
331- else {
358+ } else {
332359 marshaller .marshal (graph , result );
333360 }
334361 }
@@ -341,11 +368,9 @@ private void marshalStaxResult(Marshaller jaxbMarshaller, Object graph, StaxResu
341368 throws JAXBException {
342369 if (staxResult .getXMLStreamWriter () != null ) {
343370 jaxbMarshaller .marshal (graph , staxResult .getXMLStreamWriter ());
344- }
345- else if (staxResult .getXMLEventWriter () != null ) {
371+ } else if (staxResult .getXMLEventWriter () != null ) {
346372 jaxbMarshaller .marshal (graph , staxResult .getXMLEventWriter ());
347- }
348- else {
373+ } else {
349374 throw new IllegalArgumentException ("StaxResult contains neither XMLStreamWriter nor XMLEventConsumer" );
350375 }
351376 }
@@ -366,8 +391,7 @@ public Object unmarshal(Source source, MimeContainer mimeContainer) throws XmlMa
366391 }
367392 if (source instanceof StaxSource ) {
368393 return unmarshalStaxSource (unmarshaller , (StaxSource ) source );
369- }
370- else {
394+ } else {
371395 return unmarshaller .unmarshal (source );
372396 }
373397 }
@@ -379,11 +403,9 @@ public Object unmarshal(Source source, MimeContainer mimeContainer) throws XmlMa
379403 private Object unmarshalStaxSource (Unmarshaller jaxbUnmarshaller , StaxSource staxSource ) throws JAXBException {
380404 if (staxSource .getXMLStreamReader () != null ) {
381405 return jaxbUnmarshaller .unmarshal (staxSource .getXMLStreamReader ());
382- }
383- else if (staxSource .getXMLEventReader () != null ) {
406+ } else if (staxSource .getXMLEventReader () != null ) {
384407 return jaxbUnmarshaller .unmarshal (staxSource .getXMLEventReader ());
385- }
386- else {
408+ } else {
387409 throw new IllegalArgumentException ("StaxSource contains neither XMLStreamReader nor XMLEventReader" );
388410 }
389411 }
0 commit comments