Marshaller interface for Castor. By default, Castor does not require any further
- * configuration, though setting a target class or providing a mapping file can be used to have more control over the
+ * configuration, though setting target classes, target packages or providing a mapping file can be used to have more control over the
* behavior of Castor.
*
* If a target class is specified using setTargetClass, the CastorMarshaller can only be
@@ -74,6 +74,7 @@ import org.springframework.util.xml.StaxUtils;
* @author Arjen Poutsma
* @see #setEncoding(String)
* @see #setTargetClass(Class)
+ * @see #setTargetPackages(String[])
* @see #setMappingLocation(Resource)
* @see #setMappingLocations(Resource[])
* @since 3.0
@@ -90,7 +91,9 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
private String encoding = DEFAULT_ENCODING;
- private Class targetClass;
+ private Class[] targetClasses;
+
+ private String[] targetPackages;
private boolean validating = false;
@@ -132,12 +135,28 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
}
/**
- * Set the Castor target class. If this property is set, this CastorMarshaller
- * is tied to this one specific class. Use a mapping file for unmarshalling multiple classes.
- *
You cannot set both this property and the mapping (location).
+ * Set the Castor target class. Alternative means of configuring
+ * The default implementation loads mapping files if defined, and the target class if not defined.
+ *
+ * The default implementation loads mapping files if defined, or the target class or packages if defined.
+ *
* @return the created resolver
* @throws MappingException when the mapping file cannot be loaded
- * @throws IOException in case of I/O errors
+ * @throws IOException in case of I/O errors
* @see XMLContext#addMapping(org.exolab.castor.mapping.Mapping)
* @see XMLContext#addClass(Class)
*/
- protected XMLContext createXMLContext(Resource[] mappingLocations, Class targetClass)
+ protected XMLContext createXMLContext(Resource[] mappingLocations, Class[] targetClasses, String[] targetPackages)
throws MappingException, ResolverException, IOException {
XMLContext context = new XMLContext();
@@ -258,13 +286,15 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
}
context.addMapping(mapping);
}
- if (targetClass != null) {
- context.addClass(targetClass);
+ if (!ObjectUtils.isEmpty(targetClasses)) {
+ context.addClasses(targetClasses);
+ }
+ if (!ObjectUtils.isEmpty(targetPackages)) {
+ context.addPackages(targetPackages);
}
return context;
}
-
/**
* Returns The default implementation invokes {@link Unmarshaller#setValidation(boolean)},
- * {@link Unmarshaller#setWhitespacePreserve(boolean)}, {@link Unmarshaller#setIgnoreExtraAttributes(boolean)},
- * and {@link Unmarshaller#setIgnoreExtraElements(boolean)} with the properties set on this marshaller.
+ * Template method that allows for customizing of the given Castor
+ * {@link Unmarshaller}.
+ *
+ * The default implementation invokes
+ * {@link Unmarshaller#setValidation(boolean)},
+ * {@link Unmarshaller#setWhitespacePreserve(boolean)},
+ * {@link Unmarshaller#setIgnoreExtraAttributes(boolean)}, and
+ * {@link Unmarshaller#setIgnoreExtraElements(boolean)} with the properties
+ * set on this marshaller.
*/
protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
unmarshaller.setValidation(this.validating);
@@ -433,13 +463,16 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
}
/**
- * Convert the given A boolean flag is used to indicate whether this exception occurs during marshalling or
- * unmarshalling, since Castor itself does not make this distinction in its exception hierarchy.
- * @param ex Castor
+ * A boolean flag is used to indicate whether this exception occurs during
+ * marshalling or unmarshalling, since Castor itself does not make this
+ * distinction in its exception hierarchy.
+ *
+ * @param ex Castor CastorMarshaller for unmarshalling multiple classes include
+ * use of mapping files, and specifying packages with Castor descriptor classes.
*/
public void setTargetClass(Class targetClass) {
- this.targetClass = targetClass;
+ this.targetClasses = new Class[]{targetClass};
+ }
+
+ /**
+ * Set the Castor target classes. Alternative means of configuring
+ * CastorMarshaller for unmarshalling multiple classes include
+ * use of mapping files, and specifying packages with Castor descriptor classes.
+ */
+ public void setTargetClasses(Class[] targetClasses) {
+ this.targetClasses = targetClasses;
+ }
+
+ /**
+ * Set the package names of packages with the Castor descriptor classes.
+ */
+ public void setTargetPackages(String[] targetPackages) {
+ this.targetPackages = targetPackages;
}
/**
@@ -214,21 +233,28 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
this.suppressXsiType = suppressXsiType;
}
-
public final void afterPropertiesSet() throws CastorMappingException, IOException {
if (logger.isInfoEnabled()) {
- if (this.mappingLocations != null) {
- logger.info("Configured using " + StringUtils.arrayToCommaDelimitedString(this.mappingLocations));
+ if (!ObjectUtils.isEmpty(this.mappingLocations)) {
+ logger.info(
+ "Configured using [" + StringUtils.arrayToCommaDelimitedString(this.mappingLocations) + "]");
+ }
+ if (!ObjectUtils.isEmpty(this.targetClasses)) {
+ logger.info("Configured for target classes " + StringUtils.arrayToCommaDelimitedString(targetClasses) +
+ "]");
}
- if (this.targetClass != null) {
- logger.info("Configured for target class [" + this.targetClass.getName() + "]");
+ if (!ObjectUtils.isEmpty(this.targetPackages)) {
+ logger.info(
+ "Configured for target packages [" + StringUtils.arrayToCommaDelimitedString(targetPackages) +
+ "]");
}
- if (this.mappingLocations == null && this.targetClass == null) {
+ if (ObjectUtils.isEmpty(this.mappingLocations) && ObjectUtils.isEmpty(this.targetClasses) &&
+ ObjectUtils.isEmpty(this.targetPackages)) {
logger.info("Using default configuration");
}
}
try {
- this.xmlContext = createXMLContext(this.mappingLocations, this.targetClass);
+ this.xmlContext = createXMLContext(this.mappingLocations, this.targetClasses, this.targetPackages);
}
catch (MappingException ex) {
throw new CastorMappingException("Could not load Castor mapping", ex);
@@ -240,14 +266,16 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
/**
* Create the Castor XMLContext. Subclasses can override this to create a custom context.
- * true for all classes, i.e. Castor supports arbitrary classes.
*/
@@ -272,7 +302,6 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
return true;
}
-
// Marshalling
@Override
@@ -378,7 +407,7 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
return unmarshalSaxReader(reader, new InputSource());
}
catch (IOException ex) {
- throw new UnmarshallingFailureException("Failed to read XML stream", ex);
+ throw new UnmarshallingFailureException("Failed to read XML stream", ex);
}
}
@@ -411,19 +440,20 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
private Unmarshaller createUnmarshaller() {
Unmarshaller unmarshaller = this.xmlContext.createUnmarshaller();
- if (this.targetClass != null) {
- unmarshaller.setClass(this.targetClass);
- unmarshaller.setClassLoader(this.targetClass.getClassLoader());
- }
customizeUnmarshaller(unmarshaller);
return unmarshaller;
}
/**
- * Template method that allows for customizing of the given Castor {@link Unmarshaller}.
- * XMLException to an appropriate exception from the
- * org.springframework.oxm hierarchy.
- * XMLException that occured
- * @param marshalling indicates whether the exception occurs during marshalling (true),
- * or unmarshalling (false)
+ * Convert the given XMLException to an appropriate exception
+ * from the org.springframework.oxm hierarchy.
+ * XMLException that occured
+ * @param marshalling indicates whether the exception occurs during
+ * marshalling (true), or unmarshalling (false)
* @return the corresponding XmlMappingException
*/
protected XmlMappingException convertCastorException(XMLException ex, boolean marshalling) {
@@ -448,7 +481,7 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
}
else if (ex instanceof MarshalException) {
if (marshalling) {
- return new MarshallingFailureException("Castor marshalling exception", ex);
+ return new MarshallingFailureException("Castor marshalling exception", ex);
}
else {
return new UnmarshallingFailureException("Castor unmarshalling exception", ex);
diff --git a/org.springframework.oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java b/org.springframework.oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java
index 5171f33bccd..d79ab94c39a 100644
--- a/org.springframework.oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java
+++ b/org.springframework.oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java
@@ -19,7 +19,6 @@ package org.springframework.oxm.castor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
-import java.util.ArrayList;
import javax.xml.transform.stream.StreamSource;
import static org.junit.Assert.*;
@@ -44,7 +43,7 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests {
protected void testFlight(Object o) {
Flight flight = (Flight) o;
assertNotNull("Flight is null", flight);
- assertEquals("Number is invalid", 42L, flight.getNumber());
+ assertEquals("Number is invalid", Long.valueOf(42L), flight.getNumber());
}
@Override
@@ -59,7 +58,7 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests {
@Test
public void unmarshalTargetClass() throws Exception {
CastorMarshaller unmarshaller = new CastorMarshaller();
- unmarshaller.setTargetClass(Flights.class);
+ unmarshaller.setTargetClasses(new Class[] { Flights.class } );
unmarshaller.afterPropertiesSet();
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8")));
Object flights = unmarshaller.unmarshal(source);
@@ -67,10 +66,10 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests {
}
@Test
- public void testSetBothTargetClassAndMapping() throws IOException {
+ public void testSetBothTargetClassesAndMapping() throws IOException {
CastorMarshaller unmarshaller = new CastorMarshaller();
unmarshaller.setMappingLocation(new ClassPathResource("order-mapping.xml", CastorMarshaller.class));
- unmarshaller.setTargetClass(ArrayList.class);
+ unmarshaller.setTargetClasses(new Class[] { Order.class } );
unmarshaller.afterPropertiesSet();
String xml = "