61
61
62
62
/**
63
63
* Implementation of the <code>Marshaller</code> interface for Castor. By default, Castor does not require any further
64
- * configuration, though setting a target class or providing a mapping file can be used to have more control over the
64
+ * configuration, though setting target classes, target packages or providing a mapping file can be used to have more control over the
65
65
* behavior of Castor.
66
66
*
67
67
* <p>If a target class is specified using <code>setTargetClass</code>, the <code>CastorMarshaller</code> can only be
74
74
* @author Arjen Poutsma
75
75
* @see #setEncoding(String)
76
76
* @see #setTargetClass(Class)
77
+ * @see #setTargetPackages(String[])
77
78
* @see #setMappingLocation(Resource)
78
79
* @see #setMappingLocations(Resource[])
79
80
* @since 3.0
@@ -90,7 +91,9 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
90
91
91
92
private String encoding = DEFAULT_ENCODING ;
92
93
93
- private Class targetClass ;
94
+ private Class [] targetClasses ;
95
+
96
+ private String [] targetPackages ;
94
97
95
98
private boolean validating = false ;
96
99
@@ -132,12 +135,28 @@ public void setMappingLocations(Resource[] mappingLocations) {
132
135
}
133
136
134
137
/**
135
- * Set the Castor target class. If this property is set, this <code>CastorMarshaller</code>
136
- * is tied to this one specific class. Use a mapping file for unmarshalling multiple classes.
137
- * <p>You cannot set both this property and the mapping (location) .
138
+ * Set the Castor target class. Alternative means of configuring
139
+ * <code>CastorMarshaller<code> for unmarshalling multiple classes include
140
+ * use of mapping files, and specifying packages with Castor descriptor classes .
138
141
*/
139
142
public void setTargetClass (Class targetClass ) {
140
- this .targetClass = targetClass ;
143
+ this .targetClasses = new Class []{targetClass };
144
+ }
145
+
146
+ /**
147
+ * Set the Castor target classes. Alternative means of configuring
148
+ * <code>CastorMarshaller<code> for unmarshalling multiple classes include
149
+ * use of mapping files, and specifying packages with Castor descriptor classes.
150
+ */
151
+ public void setTargetClasses (Class [] targetClasses ) {
152
+ this .targetClasses = targetClasses ;
153
+ }
154
+
155
+ /**
156
+ * Set the package names of packages with the Castor descriptor classes.
157
+ */
158
+ public void setTargetPackages (String [] targetPackages ) {
159
+ this .targetPackages = targetPackages ;
141
160
}
142
161
143
162
/**
@@ -214,21 +233,28 @@ public void setSuppressXsiType(boolean suppressXsiType) {
214
233
this .suppressXsiType = suppressXsiType ;
215
234
}
216
235
217
-
218
236
public final void afterPropertiesSet () throws CastorMappingException , IOException {
219
237
if (logger .isInfoEnabled ()) {
220
- if (this .mappingLocations != null ) {
221
- logger .info ("Configured using " + StringUtils .arrayToCommaDelimitedString (this .mappingLocations ));
238
+ if (!ObjectUtils .isEmpty (this .mappingLocations )) {
239
+ logger .info (
240
+ "Configured using [" + StringUtils .arrayToCommaDelimitedString (this .mappingLocations ) + "]" );
241
+ }
242
+ if (!ObjectUtils .isEmpty (this .targetClasses )) {
243
+ logger .info ("Configured for target classes " + StringUtils .arrayToCommaDelimitedString (targetClasses ) +
244
+ "]" );
222
245
}
223
- if (this .targetClass != null ) {
224
- logger .info ("Configured for target class [" + this .targetClass .getName () + "]" );
246
+ if (!ObjectUtils .isEmpty (this .targetPackages )) {
247
+ logger .info (
248
+ "Configured for target packages [" + StringUtils .arrayToCommaDelimitedString (targetPackages ) +
249
+ "]" );
225
250
}
226
- if (this .mappingLocations == null && this .targetClass == null ) {
251
+ if (ObjectUtils .isEmpty (this .mappingLocations ) && ObjectUtils .isEmpty (this .targetClasses ) &&
252
+ ObjectUtils .isEmpty (this .targetPackages )) {
227
253
logger .info ("Using default configuration" );
228
254
}
229
255
}
230
256
try {
231
- this .xmlContext = createXMLContext (this .mappingLocations , this .targetClass );
257
+ this .xmlContext = createXMLContext (this .mappingLocations , this .targetClasses , this . targetPackages );
232
258
}
233
259
catch (MappingException ex ) {
234
260
throw new CastorMappingException ("Could not load Castor mapping" , ex );
@@ -240,14 +266,16 @@ public final void afterPropertiesSet() throws CastorMappingException, IOExceptio
240
266
241
267
/**
242
268
* Create the Castor <code>XMLContext</code>. Subclasses can override this to create a custom context.
243
- * <p>The default implementation loads mapping files if defined, and the target class if not defined.
269
+ * <p>
270
+ * The default implementation loads mapping files if defined, or the target class or packages if defined.
271
+ *
244
272
* @return the created resolver
245
273
* @throws MappingException when the mapping file cannot be loaded
246
- * @throws IOException in case of I/O errors
274
+ * @throws IOException in case of I/O errors
247
275
* @see XMLContext#addMapping(org.exolab.castor.mapping.Mapping)
248
276
* @see XMLContext#addClass(Class)
249
277
*/
250
- protected XMLContext createXMLContext (Resource [] mappingLocations , Class targetClass )
278
+ protected XMLContext createXMLContext (Resource [] mappingLocations , Class [] targetClasses , String [] targetPackages )
251
279
throws MappingException , ResolverException , IOException {
252
280
253
281
XMLContext context = new XMLContext ();
@@ -258,21 +286,22 @@ protected XMLContext createXMLContext(Resource[] mappingLocations, Class targetC
258
286
}
259
287
context .addMapping (mapping );
260
288
}
261
- if (targetClass != null ) {
262
- context .addClass (targetClass );
289
+ if (!ObjectUtils .isEmpty (targetClasses )) {
290
+ context .addClasses (targetClasses );
291
+ }
292
+ if (!ObjectUtils .isEmpty (targetPackages )) {
293
+ context .addPackages (targetPackages );
263
294
}
264
295
return context ;
265
296
}
266
297
267
-
268
298
/**
269
299
* Returns <code>true</code> for all classes, i.e. Castor supports arbitrary classes.
270
300
*/
271
301
public boolean supports (Class <?> clazz ) {
272
302
return true ;
273
303
}
274
304
275
-
276
305
// Marshalling
277
306
278
307
@ Override
@@ -378,7 +407,7 @@ protected final Object unmarshalXmlEventReader(XMLEventReader eventReader) {
378
407
return unmarshalSaxReader (reader , new InputSource ());
379
408
}
380
409
catch (IOException ex ) {
381
- throw new UnmarshallingFailureException ("Failed to read XML stream" , ex );
410
+ throw new UnmarshallingFailureException ("Failed to read XML stream" , ex );
382
411
}
383
412
}
384
413
@@ -411,19 +440,20 @@ protected final Object unmarshalXmlStreamReader(XMLStreamReader streamReader) {
411
440
412
441
private Unmarshaller createUnmarshaller () {
413
442
Unmarshaller unmarshaller = this .xmlContext .createUnmarshaller ();
414
- if (this .targetClass != null ) {
415
- unmarshaller .setClass (this .targetClass );
416
- unmarshaller .setClassLoader (this .targetClass .getClassLoader ());
417
- }
418
443
customizeUnmarshaller (unmarshaller );
419
444
return unmarshaller ;
420
445
}
421
446
422
447
/**
423
- * Template method that allows for customizing of the given Castor {@link Unmarshaller}.
424
- * <p>The default implementation invokes {@link Unmarshaller#setValidation(boolean)},
425
- * {@link Unmarshaller#setWhitespacePreserve(boolean)}, {@link Unmarshaller#setIgnoreExtraAttributes(boolean)},
426
- * and {@link Unmarshaller#setIgnoreExtraElements(boolean)} with the properties set on this marshaller.
448
+ * Template method that allows for customizing of the given Castor
449
+ * {@link Unmarshaller}.
450
+ * <p>
451
+ * The default implementation invokes
452
+ * {@link Unmarshaller#setValidation(boolean)},
453
+ * {@link Unmarshaller#setWhitespacePreserve(boolean)},
454
+ * {@link Unmarshaller#setIgnoreExtraAttributes(boolean)}, and
455
+ * {@link Unmarshaller#setIgnoreExtraElements(boolean)} with the properties
456
+ * set on this marshaller.
427
457
*/
428
458
protected void customizeUnmarshaller (Unmarshaller unmarshaller ) {
429
459
unmarshaller .setValidation (this .validating );
@@ -433,13 +463,16 @@ protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
433
463
}
434
464
435
465
/**
436
- * Convert the given <code>XMLException</code> to an appropriate exception from the
437
- * <code>org.springframework.oxm</code> hierarchy.
438
- * <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
439
- * unmarshalling, since Castor itself does not make this distinction in its exception hierarchy.
440
- * @param ex Castor <code>XMLException</code> that occured
441
- * @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
442
- * or unmarshalling (<code>false</code>)
466
+ * Convert the given <code>XMLException</code> to an appropriate exception
467
+ * from the <code>org.springframework.oxm</code> hierarchy.
468
+ * <p>
469
+ * A boolean flag is used to indicate whether this exception occurs during
470
+ * marshalling or unmarshalling, since Castor itself does not make this
471
+ * distinction in its exception hierarchy.
472
+ *
473
+ * @param ex Castor <code>XMLException</code> that occured
474
+ * @param marshalling indicates whether the exception occurs during
475
+ * marshalling (<code>true</code>), or unmarshalling (<code>false</code>)
443
476
* @return the corresponding <code>XmlMappingException</code>
444
477
*/
445
478
protected XmlMappingException convertCastorException (XMLException ex , boolean marshalling ) {
@@ -448,7 +481,7 @@ protected XmlMappingException convertCastorException(XMLException ex, boolean ma
448
481
}
449
482
else if (ex instanceof MarshalException ) {
450
483
if (marshalling ) {
451
- return new MarshallingFailureException ("Castor marshalling exception" , ex );
484
+ return new MarshallingFailureException ("Castor marshalling exception" , ex );
452
485
}
453
486
else {
454
487
return new UnmarshallingFailureException ("Castor unmarshalling exception" , ex );
0 commit comments