Remove Castor marshaller

Resolves #22250
This commit is contained in:
Arjen Poutsma 2019-01-14 11:25:27 +01:00
parent bfff9ca0ce
commit 89a7e752ef
19 changed files with 14 additions and 1686 deletions

View File

@ -22,7 +22,7 @@ _Within your locally cloned `spring-framework` working directory:_
to directory -> Select Finish)
3. If prompted, exclude the `spring-aspects` module (or after the import by closing or
deleting the project)
4. In the `spring-oxm` project, add the two folders (`castor` and `jaxb`) in
4. In the `spring-oxm` project, add the `jaxb` folder in
`build/generated-sources` to the build path (right click on them and select
`Build Path -> Use as Source Folder`)
5. To apply project specific settings run `./gradlew eclipseBuildship`

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ package org.apache.commons.logging;
* <p><b>Note that this Commons Logging variant is only meant to be used for
* infrastructure logging purposes in the core framework and in extensions.</b>
* It also serves as a common bridge for third-party libraries using the
* Commons Logging API, e.g. Apache HttpClient, Castor and HtmlUnit, bringing
* Commons Logging API, e.g. Apache HttpClient, and HtmlUnit, bringing
* them into the same consistent arrangement without any extra bridge jars.
*
* <p><b>For logging need in application code, prefer direct use of Log4j 2.x

View File

@ -1 +0,0 @@
org.exolab.castor.builder.primitivetowrapper=true

View File

@ -1,13 +1,11 @@
description = "Spring Object/XML Marshalling"
configurations {
castor
jibx
xjc
}
dependencies {
castor "org.codehaus.castor:castor-anttasks:1.4.1"
jibx "org.jibx:jibx-bind:1.3.1"
jibx "org.apache.bcel:bcel:6.0"
xjc "javax.xml.bind:jaxb-api:2.3.1"
@ -20,45 +18,6 @@ dependencies {
ext.genSourcesDir = "${buildDir}/generated-sources"
ext.flightSchema = "${projectDir}/src/test/resources/org/springframework/oxm/flight.xsd"
task genCastor {
def orderSchema = "${projectDir}/src/test/resources/org/springframework/oxm/order.xsd"
def castorBuilderProperties = "${projectDir}/src/test/castor/castorbuilder.properties"
ext.sourcesDir = "${genSourcesDir}/castor"
ext.classesDir = "${buildDir}/classes/castor"
inputs.files flightSchema, orderSchema, castorBuilderProperties
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "castor", classname: "org.castor.anttask.CastorCodeGenTask",
classpath: configurations.castor.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
castor(types: "j2", warnings: false, file: flightSchema, todir: sourcesDir,
package: "org.springframework.oxm.castor", properties: castorBuilderProperties)
castor(types: "j2", warnings: false, file: orderSchema, todir: sourcesDir,
package: "org.springframework.oxm.castor", properties: castorBuilderProperties)
javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
debugLevel: "lines,vars,source", classpath: configurations.castor.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
task genJaxb {
ext.sourcesDir = "${genSourcesDir}/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
@ -100,11 +59,6 @@ dependencies {
compile(project(":spring-core"))
optional("javax.xml.bind:jaxb-api:2.3.1")
optional("javax.activation:javax.activation-api:1.2.0")
optional("org.codehaus.castor:castor-xml:1.4.1") {
exclude group: "stax", module: "stax-api"
exclude group: "org.springframework", module: "spring-context"
exclude group: "commons-logging", module: "commons-logging"
}
optional("com.thoughtworks.xstream:xstream:1.4.10") {
exclude group: "xpp3", module: "xpp3_min"
exclude group: "xmlpull", module: "xmlpull"
@ -115,10 +69,8 @@ dependencies {
testCompile("org.codehaus.jettison:jettison:1.3.8") {
exclude group: "stax", module: "stax-api"
}
testCompile(files(genCastor.classesDir).builtBy(genCastor))
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile("org.xmlunit:xmlunit-matchers:2.6.2")
testRuntime("xerces:xercesImpl:2.11.0") // for Castor
testRuntime("com.sun.xml.bind:jaxb-core:2.3.0.1")
testRuntime("com.sun.xml.bind:jaxb-impl:2.3.0.1")
}

View File

@ -1,42 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.castor;
import org.springframework.oxm.XmlMappingException;
/**
* Exception thrown by {@link CastorMarshaller} whenever it encounters a mapping problem.
*
* @author Juergen Hoeller
* @since 3.0
* @deprecated as of Spring Framework 4.3.13, due to the lack of activity on the Castor project
*/
@Deprecated
@SuppressWarnings("serial")
public class CastorMappingException extends XmlMappingException {
/**
* Construct a {@code CastorMappingException} with the specified detail message
* and nested exception.
* @param msg the detail message
* @param cause the nested exception
*/
public CastorMappingException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@ -1,734 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.castor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Map;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.util.ObjectFactory;
import org.exolab.castor.xml.IDResolver;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.ResolverException;
import org.exolab.castor.xml.UnmarshalHandler;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.exolab.castor.xml.XMLClassDescriptorResolver;
import org.exolab.castor.xml.XMLContext;
import org.exolab.castor.xml.XMLException;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.oxm.MarshallingFailureException;
import org.springframework.oxm.UncategorizedMappingException;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.ValidationFailureException;
import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.support.AbstractMarshaller;
import org.springframework.oxm.support.SaxResourceUtils;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.util.xml.StaxUtils;
/**
* Implementation of the {@code Marshaller} interface for Castor. By default, Castor does
* not require any further configuration, though setting target classes, target packages or
* providing a mapping file can be used to have more control over the behavior of Castor.
*
* <p>If a target class is specified using {@code setTargetClass}, the {@code CastorMarshaller}
* can only be used to unmarshal XML that represents that specific class. If you want to unmarshal
* multiple classes, you have to provide a mapping file using {@code setMappingLocations}.
*
* <p>Due to limitations of Castor's API, it is required to set the encoding used for writing
* to output streams. It defaults to {@code UTF-8}.
*
* @author Arjen Poutsma
* @author Jakub Narloch
* @author Juergen Hoeller
* @since 3.0
* @see #setEncoding(String)
* @see #setTargetClass(Class)
* @see #setTargetPackages(String[])
* @see #setMappingLocation(Resource)
* @see #setMappingLocations(Resource[])
* @deprecated as of Spring Framework 4.3.13, due to the lack of activity on the Castor project
*/
@Deprecated
public class CastorMarshaller extends AbstractMarshaller implements InitializingBean, BeanClassLoaderAware {
/**
* The default encoding used for stream access: UTF-8.
*/
public static final String DEFAULT_ENCODING = "UTF-8";
@Nullable
private Resource[] mappingLocations;
private String encoding = DEFAULT_ENCODING;
@Nullable
private Class<?>[] targetClasses;
@Nullable
private String[] targetPackages;
private boolean validating = false;
private boolean suppressNamespaces = false;
private boolean suppressXsiType = false;
private boolean marshalAsDocument = true;
private boolean marshalExtendedType = true;
@Nullable
private String rootElement;
@Nullable
private String noNamespaceSchemaLocation;
@Nullable
private String schemaLocation;
private boolean useXSITypeAtRoot = false;
private boolean whitespacePreserve = false;
private boolean ignoreExtraAttributes = true;
private boolean ignoreExtraElements = false;
@Nullable
private Object rootObject;
private boolean reuseObjects = false;
private boolean clearCollections = false;
@Nullable
private Map<String, String> castorProperties;
@Nullable
private Map<String, String> doctypes;
@Nullable
private Map<String, String> processingInstructions;
@Nullable
private Map<String, String> namespaceMappings;
@Nullable
private Map<String, String> namespaceToPackageMapping;
@Nullable
private EntityResolver entityResolver;
@Nullable
private XMLClassDescriptorResolver classDescriptorResolver;
@Nullable
private IDResolver idResolver;
@Nullable
private ObjectFactory objectFactory;
@Nullable
private ClassLoader beanClassLoader;
@Nullable
private XMLContext xmlContext;
/**
* Set the encoding to be used for stream access.
* @see #DEFAULT_ENCODING
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
@Override
protected String getDefaultEncoding() {
return this.encoding;
}
/**
* Set the locations of the Castor XML mapping files.
*/
public void setMappingLocation(Resource mappingLocation) {
this.mappingLocations = new Resource[]{mappingLocation};
}
/**
* Set the locations of the Castor XML mapping files.
*/
public void setMappingLocations(Resource... mappingLocations) {
this.mappingLocations = mappingLocations;
}
/**
* Set the Castor target class.
* @see #setTargetPackage
* @see #setMappingLocation
*/
public void setTargetClass(Class<?> targetClass) {
this.targetClasses = new Class<?>[] {targetClass};
}
/**
* Set the Castor target classes.
* @see #setTargetPackages
* @see #setMappingLocations
*/
public void setTargetClasses(Class<?>... targetClasses) {
this.targetClasses = targetClasses;
}
/**
* Set the name of a package with the Castor descriptor classes.
*/
public void setTargetPackage(String targetPackage) {
this.targetPackages = new String[] {targetPackage};
}
/**
* Set the names of packages with the Castor descriptor classes.
*/
public void setTargetPackages(String... targetPackages) {
this.targetPackages = targetPackages;
}
/**
* Set whether this marshaller should validate in- and outgoing documents.
* <p>Default is {@code false}.
* @see Marshaller#setValidation(boolean)
*/
public void setValidating(boolean validating) {
this.validating = validating;
}
/**
* Sets whether this marshaller should output namespaces.
* <p>The default is {@code false}, i.e. namespaces are written.
* @see org.exolab.castor.xml.Marshaller#setSuppressNamespaces(boolean)
*/
public void setSuppressNamespaces(boolean suppressNamespaces) {
this.suppressNamespaces = suppressNamespaces;
}
/**
* Set whether this marshaller should output the {@code xsi:type} attribute.
* <p>The default is {@code false}, i.e. the {@code xsi:type} is written.
* @see org.exolab.castor.xml.Marshaller#setSuppressXSIType(boolean)
*/
public void setSuppressXsiType(boolean suppressXsiType) {
this.suppressXsiType = suppressXsiType;
}
/**
* Set whether this marshaller should output the xml declaration.
* <p>The default is {@code true}, the XML declaration will be written.
* @see org.exolab.castor.xml.Marshaller#setMarshalAsDocument(boolean)
*/
public void setMarshalAsDocument(boolean marshalAsDocument) {
this.marshalAsDocument = marshalAsDocument;
}
/**
* Set whether this marshaller should output for given type the {@code xsi:type} attribute.
* <p>The default is {@code true}, the {@code xsi:type} attribute will be written.
* @see org.exolab.castor.xml.Marshaller#setMarshalExtendedType(boolean)
*/
public void setMarshalExtendedType(boolean marshalExtendedType) {
this.marshalExtendedType = marshalExtendedType;
}
/**
* Set the name of the root element.
* @see org.exolab.castor.xml.Marshaller#setRootElement(String)
*/
public void setRootElement(String rootElement) {
this.rootElement = rootElement;
}
/**
* Set the value of {@code xsi:noNamespaceSchemaLocation} attribute. When set, the
* {@code xsi:noNamespaceSchemaLocation} attribute will be written for the root element.
* @see org.exolab.castor.xml.Marshaller#setNoNamespaceSchemaLocation(String)
*/
public void setNoNamespaceSchemaLocation(String noNamespaceSchemaLocation) {
this.noNamespaceSchemaLocation = noNamespaceSchemaLocation;
}
/**
* Set the value of {@code xsi:schemaLocation} attribute. When set, the
* {@code xsi:schemaLocation} attribute will be written for the root element.
* @see org.exolab.castor.xml.Marshaller#setSchemaLocation(String)
*/
public void setSchemaLocation(String schemaLocation) {
this.schemaLocation = schemaLocation;
}
/**
* Sets whether this marshaller should output the {@code xsi:type} attribute for the root element.
* This can be useful when the type of the element can not be simply determined from the element name.
* <p>The default is {@code false}: The {@code xsi:type} attribute for the root element won't be written.
* @see org.exolab.castor.xml.Marshaller#setUseXSITypeAtRoot(boolean)
*/
public void setUseXSITypeAtRoot(boolean useXSITypeAtRoot) {
this.useXSITypeAtRoot = useXSITypeAtRoot;
}
/**
* Set whether the Castor {@link Unmarshaller} should preserve "ignorable" whitespace.
* <p>Default is {@code false}.
* @see org.exolab.castor.xml.Unmarshaller#setWhitespacePreserve(boolean)
*/
public void setWhitespacePreserve(boolean whitespacePreserve) {
this.whitespacePreserve = whitespacePreserve;
}
/**
* Set whether the Castor {@link Unmarshaller} should ignore attributes that do not match a specific field.
* <p>Default is {@code true}: Extra attributes are ignored.
* @see org.exolab.castor.xml.Unmarshaller#setIgnoreExtraAttributes(boolean)
*/
public void setIgnoreExtraAttributes(boolean ignoreExtraAttributes) {
this.ignoreExtraAttributes = ignoreExtraAttributes;
}
/**
* Set whether the Castor {@link Unmarshaller} should ignore elements that do not match a specific field.
* <p>Default is {@code false}: Extra elements are flagged as an error.
* @see org.exolab.castor.xml.Unmarshaller#setIgnoreExtraElements(boolean)
*/
public void setIgnoreExtraElements(boolean ignoreExtraElements) {
this.ignoreExtraElements = ignoreExtraElements;
}
/**
* Set the expected root object for the unmarshaller, into which the source will be unmarshalled.
* @see org.exolab.castor.xml.Unmarshaller#setObject(Object)
*/
public void setRootObject(Object root) {
this.rootObject = root;
}
/**
* Set whether this unmarshaller should re-use objects.
* This will be only used when unmarshalling to an existing object.
* <p>The default is {@code false}, which means that the objects won't be re-used.
* @see org.exolab.castor.xml.Unmarshaller#setReuseObjects(boolean)
*/
public void setReuseObjects(boolean reuseObjects) {
this.reuseObjects = reuseObjects;
}
/**
* Sets whether this unmarshaller should clear collections upon the first use.
* <p>The default is {@code false} which means that marshaller won't clear collections.
* @see org.exolab.castor.xml.Unmarshaller#setClearCollections(boolean)
*/
public void setClearCollections(boolean clearCollections) {
this.clearCollections = clearCollections;
}
/**
* Set Castor-specific properties for marshalling and unmarshalling.
* Each entry key is considered the property name and each value the property value.
* @see org.exolab.castor.xml.Marshaller#setProperty(String, String)
* @see org.exolab.castor.xml.Unmarshaller#setProperty(String, String)
*/
public void setCastorProperties(Map<String, String> castorProperties) {
this.castorProperties = castorProperties;
}
/**
* Set the map containing document type definition for the marshaller.
* Each entry has system id as key and public id as value.
* @see org.exolab.castor.xml.Marshaller#setDoctype(String, String)
*/
public void setDoctypes(Map<String, String> doctypes) {
this.doctypes = doctypes;
}
/**
* Sets the processing instructions that will be used by during marshalling.
* Keys are the processing targets and values contain the processing data.
* @see org.exolab.castor.xml.Marshaller#addProcessingInstruction(String, String)
*/
public void setProcessingInstructions(Map<String, String> processingInstructions) {
this.processingInstructions = processingInstructions;
}
/**
* Set the namespace mappings.
* Property names are interpreted as namespace prefixes; values are namespace URIs.
* @see org.exolab.castor.xml.Marshaller#setNamespaceMapping(String, String)
*/
public void setNamespaceMappings(Map<String, String> namespaceMappings) {
this.namespaceMappings = namespaceMappings;
}
/**
* Set the namespace to package mappings. Property names are represents the namespaces URI, values are packages.
* @see org.exolab.castor.xml.Marshaller#setNamespaceMapping(String, String)
*/
public void setNamespaceToPackageMapping(Map<String, String> namespaceToPackageMapping) {
this.namespaceToPackageMapping = namespaceToPackageMapping;
}
/**
* Set the {@link EntityResolver} to be used during unmarshalling.
* This resolver will used to resolve system and public ids.
* @see org.exolab.castor.xml.Unmarshaller#setEntityResolver(EntityResolver)
*/
public void setEntityResolver(EntityResolver entityResolver) {
this.entityResolver = entityResolver;
}
/**
* Set the {@link XMLClassDescriptorResolver} to be used during unmarshalling.
* This resolver will used to resolve class descriptors.
* @see org.exolab.castor.xml.Unmarshaller#setResolver(XMLClassDescriptorResolver)
*/
public void setClassDescriptorResolver(XMLClassDescriptorResolver classDescriptorResolver) {
this.classDescriptorResolver = classDescriptorResolver;
}
/**
* Set the Castor {@link IDResolver} to be used during unmarshalling.
* @see org.exolab.castor.xml.Unmarshaller#setIDResolver(IDResolver)
*/
public void setIdResolver(IDResolver idResolver) {
this.idResolver = idResolver;
}
/**
* Set the Castor {@link ObjectFactory} to be used during unmarshalling.
* @see org.exolab.castor.xml.Unmarshaller#setObjectFactory(ObjectFactory)
*/
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void afterPropertiesSet() throws CastorMappingException, IOException {
try {
this.xmlContext = createXMLContext(this.mappingLocations, this.targetClasses, this.targetPackages);
}
catch (MappingException ex) {
throw new CastorMappingException("Could not load Castor mapping", ex);
}
catch (ResolverException ex) {
throw new CastorMappingException("Could not resolve Castor mapping", ex);
}
}
/**
* Create the Castor {@code XMLContext}. Subclasses can override this to create a custom context.
* <p>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
* @see XMLContext#addMapping(org.exolab.castor.mapping.Mapping)
* @see XMLContext#addClass(Class)
*/
protected XMLContext createXMLContext(@Nullable Resource[] mappingLocations,
@Nullable Class<?>[] targetClasses, @Nullable String[] targetPackages)
throws MappingException, ResolverException, IOException {
XMLContext context = new XMLContext();
if (!ObjectUtils.isEmpty(mappingLocations)) {
Mapping mapping = new Mapping();
for (Resource mappingLocation : mappingLocations) {
mapping.loadMapping(SaxResourceUtils.createInputSource(mappingLocation));
}
context.addMapping(mapping);
}
if (!ObjectUtils.isEmpty(targetClasses)) {
context.addClasses(targetClasses);
}
if (!ObjectUtils.isEmpty(targetPackages)) {
context.addPackages(targetPackages);
}
if (this.castorProperties != null) {
this.castorProperties.forEach(context::setProperty);
}
return context;
}
/**
* Returns {@code true} for all classes, i.e. Castor supports arbitrary classes.
*/
@Override
public boolean supports(Class<?> clazz) {
return true;
}
// Marshalling
@Override
protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
marshalSaxHandlers(graph, DomUtils.createContentHandler(node), null);
}
@Override
protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException {
ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter);
LexicalHandler lexicalHandler = null;
if (contentHandler instanceof LexicalHandler) {
lexicalHandler = (LexicalHandler) contentHandler;
}
marshalSaxHandlers(graph, contentHandler, lexicalHandler);
}
@Override
protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
ContentHandler contentHandler = StaxUtils.createContentHandler(streamWriter);
LexicalHandler lexicalHandler = null;
if (contentHandler instanceof LexicalHandler) {
lexicalHandler = (LexicalHandler) contentHandler;
}
marshalSaxHandlers(graph, StaxUtils.createContentHandler(streamWriter), lexicalHandler);
}
@Override
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, @Nullable LexicalHandler lexicalHandler)
throws XmlMappingException {
Assert.state(this.xmlContext != null, "CastorMarshaller not initialized");
Marshaller marshaller = this.xmlContext.createMarshaller();
marshaller.setContentHandler(contentHandler);
doMarshal(graph, marshaller);
}
@Override
protected void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException {
marshalWriter(graph, new OutputStreamWriter(outputStream, this.encoding));
}
@Override
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
Assert.state(this.xmlContext != null, "CastorMarshaller not initialized");
Marshaller marshaller = this.xmlContext.createMarshaller();
marshaller.setWriter(writer);
doMarshal(graph, marshaller);
}
private void doMarshal(Object graph, Marshaller marshaller) {
try {
customizeMarshaller(marshaller);
marshaller.marshal(graph);
}
catch (XMLException ex) {
throw convertCastorException(ex, true);
}
}
/**
* Template method that allows for customizing of the given Castor {@link Marshaller}.
*/
protected void customizeMarshaller(Marshaller marshaller) {
marshaller.setValidation(this.validating);
marshaller.setSuppressNamespaces(this.suppressNamespaces);
marshaller.setSuppressXSIType(this.suppressXsiType);
marshaller.setMarshalAsDocument(this.marshalAsDocument);
marshaller.setMarshalExtendedType(this.marshalExtendedType);
marshaller.setRootElement(this.rootElement);
marshaller.setNoNamespaceSchemaLocation(this.noNamespaceSchemaLocation);
marshaller.setSchemaLocation(this.schemaLocation);
marshaller.setUseXSITypeAtRoot(this.useXSITypeAtRoot);
if (this.doctypes != null) {
this.doctypes.forEach(marshaller::setDoctype);
}
if (this.processingInstructions != null) {
this.processingInstructions.forEach(marshaller::addProcessingInstruction);
}
if (this.namespaceMappings != null) {
this.namespaceMappings.forEach(marshaller::setNamespaceMapping);
}
}
// Unmarshalling
@Override
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
try {
return createUnmarshaller().unmarshal(node);
}
catch (XMLException ex) {
throw convertCastorException(ex, false);
}
}
@Override
protected Object unmarshalXmlEventReader(XMLEventReader eventReader) {
try {
return createUnmarshaller().unmarshal(eventReader);
}
catch (XMLException ex) {
throw convertCastorException(ex, false);
}
}
@Override
protected Object unmarshalXmlStreamReader(XMLStreamReader streamReader) {
try {
return createUnmarshaller().unmarshal(streamReader);
}
catch (XMLException ex) {
throw convertCastorException(ex, false);
}
}
@Override
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
throws XmlMappingException, IOException {
UnmarshalHandler unmarshalHandler = createUnmarshaller().createHandler();
try {
ContentHandler contentHandler = Unmarshaller.getContentHandler(unmarshalHandler);
xmlReader.setContentHandler(contentHandler);
xmlReader.parse(inputSource);
return unmarshalHandler.getObject();
}
catch (SAXException ex) {
throw new UnmarshallingFailureException("SAX reader exception", ex);
}
}
@Override
protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
try {
return createUnmarshaller().unmarshal(new InputSource(inputStream));
}
catch (XMLException ex) {
throw convertCastorException(ex, false);
}
}
@Override
protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
try {
return createUnmarshaller().unmarshal(new InputSource(reader));
}
catch (XMLException ex) {
throw convertCastorException(ex, false);
}
}
private Unmarshaller createUnmarshaller() {
Assert.state(this.xmlContext != null, "CastorMarshaller not initialized");
Unmarshaller unmarshaller = this.xmlContext.createUnmarshaller();
customizeUnmarshaller(unmarshaller);
return unmarshaller;
}
/**
* Template method that allows for customizing of the given Castor {@link Unmarshaller}.
*/
protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
unmarshaller.setValidation(this.validating);
unmarshaller.setWhitespacePreserve(this.whitespacePreserve);
unmarshaller.setIgnoreExtraAttributes(this.ignoreExtraAttributes);
unmarshaller.setIgnoreExtraElements(this.ignoreExtraElements);
unmarshaller.setObject(this.rootObject);
unmarshaller.setReuseObjects(this.reuseObjects);
unmarshaller.setClearCollections(this.clearCollections);
if (this.namespaceToPackageMapping != null) {
this.namespaceToPackageMapping.forEach(unmarshaller::addNamespaceToPackageMapping);
}
if (this.entityResolver != null) {
unmarshaller.setEntityResolver(this.entityResolver);
}
if (this.classDescriptorResolver != null) {
unmarshaller.setResolver(this.classDescriptorResolver);
}
if (this.idResolver != null) {
unmarshaller.setIDResolver(this.idResolver);
}
if (this.objectFactory != null) {
unmarshaller.setObjectFactory(this.objectFactory);
}
if (this.beanClassLoader != null) {
unmarshaller.setClassLoader(this.beanClassLoader);
}
}
/**
* Convert the given {@code XMLException} to an appropriate exception from the
* {@code org.springframework.oxm} hierarchy.
* <p>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 the Castor {@code XMLException} that occurred
* @param marshalling indicates whether the exception occurs during marshalling ({@code true}),
* or unmarshalling ({@code false})
* @return the corresponding {@code XmlMappingException}
*/
protected XmlMappingException convertCastorException(XMLException ex, boolean marshalling) {
if (ex instanceof ValidationException) {
return new ValidationFailureException("Castor validation exception", ex);
}
else if (ex instanceof MarshalException) {
if (marshalling) {
return new MarshallingFailureException("Castor marshalling exception", ex);
}
else {
return new UnmarshallingFailureException("Castor unmarshalling exception", ex);
}
}
else {
// fallback
return new UncategorizedMappingException("Unknown Castor exception", ex);
}
}
}

View File

@ -1,10 +0,0 @@
/**
* Package providing integration of <a href="http://castor-data-binding.github.io/castor/reference-guides/1.3.3/html-single/index.html#xml.mapping">Castor</a>
* within Spring's O/X Mapping support.
*/
@NonNullApi
@NonNullFields
package org.springframework.oxm.castor;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@ -1,38 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
/**
* Parser for the {@code <oxm:castor-marshaller/>} element.
*
* @author Jakub Narloch
* @since 3.1
* @deprecated as of Spring Framework 4.3.13, due to the lack of activity on the Castor project
*/
@Deprecated
class CastorMarshallerBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.oxm.castor.CastorMarshaller";
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,7 +32,6 @@ public class OxmNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("jaxb2-marshaller", new Jaxb2MarshallerBeanDefinitionParser());
registerBeanDefinitionParser("jibx-marshaller", new JibxMarshallerBeanDefinitionParser());
registerBeanDefinitionParser("castor-marshaller", new CastorMarshallerBeanDefinitionParser());
}
}

View File

@ -80,46 +80,6 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="castor-marshaller">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation
source="java:org.springframework.oxm.castor.CastorMarshaller">
Defines a Castor Marshaller. Deprecated as of Spring Framework 4.3.13!
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.oxm.castor.CastorMarshaller" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="encoding" type="xsd:string">
<xsd:annotation>
<xsd:documentation>The encoding to use for stream reading.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="target-class" type="classType">
<xsd:annotation>
<xsd:documentation>The target class to be bound with the Castor marshaller.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="target-package" type="xsd:string">
<xsd:annotation>
<xsd:documentation>The target package that contains Castor descriptor classes.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mapping-location" type="xsd:string">
<xsd:annotation>
<xsd:documentation>The path to the Castor mapping file.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="classType">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class">A class supported by a marshaller.</xsd:documentation>

View File

@ -1,300 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.castor;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import org.castor.xml.XMLProperties;
import org.exolab.castor.xml.XercesXMLSerializerFactory;
import org.junit.Test;
import org.mockito.InOrder;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xmlunit.builder.Input;
import org.xmlunit.xpath.JAXPXPathEngine;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.AbstractMarshallerTests;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.xmlunit.matchers.CompareMatcher.*;
/**
* Tests the {@link CastorMarshaller} class.
*
* @author Arjen Poutsma
* @author Jakub Narloch
* @author Sam Brannen
*/
@Deprecated
public class CastorMarshallerTests extends AbstractMarshallerTests<CastorMarshaller> {
/**
* Represents the expected result that doesn't contain the xml declaration.
*/
private static final String DOCUMENT_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
"<tns:flight><tns:number>42</tns:number></tns:flight></tns:flights>";
/**
* Represents the expected result that doesn't contain the xml namespaces.
*/
private static final String SUPPRESSED_NAMESPACE_EXPECTED_STRING =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><flights><flight><number>42</number></flight></flights>";
/**
* Represents the expected result with modified root element name.
*/
private static final String ROOT_ELEMENT_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<tns:canceledFlights xmlns:tns=\"http://samples.springframework.org/flight\">" +
"<tns:flight><tns:number>42</tns:number></tns:flight></tns:canceledFlights>";
/**
* Represents the expected result with 'xsi:type' attribute.
*/
private static final String XSI_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<objects><castor-object xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xmlns:java=\"http://java.sun.com\"" +
" xsi:type=\"java:org.springframework.oxm.castor.CastorObject\">" +
"<name>test</name><value>8</value></castor-object></objects>";
/**
* Represents the expected result with suppressed 'xsi:type' attribute.
*/
private static final String SUPPRESSED_XSI_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<objects><castor-object><name>test</name><value>8</value></castor-object></objects>";
/**
* Represents the expected result with 'xsi:type' attribute for root element.
*/
private static final String ROOT_WITH_XSI_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<objects xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xmlns:java=\"http://java.sun.com\"" +
" xsi:type=\"java:java.util.Arrays$ArrayList\">" +
"<castor-object xsi:type=\"java:org.springframework.oxm.castor.CastorObject\">" +
"<name>test</name><value>8</value></castor-object></objects>";
/**
* Represents the expected result without 'xsi:type' attribute for root element.
*/
private static final String ROOT_WITHOUT_XSI_EXPECTED_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<objects><castor-object xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xmlns:java=\"http://java.sun.com\"" +
" xsi:type=\"java:org.springframework.oxm.castor.CastorObject\">" +
"<name>test</name><value>8</value></castor-object></objects>";
@Override
protected CastorMarshaller createMarshaller() throws Exception {
CastorMarshaller marshaller = new CastorMarshaller();
ClassPathResource mappingLocation = new ClassPathResource("mapping.xml", CastorMarshaller.class);
marshaller.setMappingLocation(mappingLocation);
Map<String, String> props = new HashMap<>(1);
props.put(XMLProperties.SERIALIZER_FACTORY, XercesXMLSerializerFactory.class.getName());
marshaller.setCastorProperties(props);
marshaller.afterPropertiesSet();
return marshaller;
}
@Override
protected Object createFlights() {
Flight flight = new Flight();
flight.setNumber(42L);
Flights flights = new Flights();
flights.addFlight(flight);
return flights;
}
@Test
public void marshalSaxResult() throws Exception {
ContentHandler contentHandler = mock(ContentHandler.class);
SAXResult result = new SAXResult(contentHandler);
marshaller.marshal(flights, result);
InOrder ordered = inOrder(contentHandler);
ordered.verify(contentHandler).startDocument();
ordered.verify(contentHandler).startPrefixMapping("tns", "http://samples.springframework.org/flight");
ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"),
eq("flights"), eq("tns:flights"), isA(Attributes.class));
ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"),
eq("flight"), eq("tns:flight"), isA(Attributes.class));
ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"),
eq("number"), eq("tns:number"), isA(Attributes.class));
ordered.verify(contentHandler).characters(eq(new char[]{'4', '2'}), eq(0), eq(2));
ordered.verify(contentHandler).endElement("http://samples.springframework.org/flight", "number", "tns:number");
ordered.verify(contentHandler).endElement("http://samples.springframework.org/flight", "flight", "tns:flight");
ordered.verify(contentHandler).endElement("http://samples.springframework.org/flight", "flights", "tns:flights");
ordered.verify(contentHandler).endPrefixMapping("tns");
ordered.verify(contentHandler).endDocument();
}
@Test
public void supports() throws Exception {
assertTrue("CastorMarshaller does not support Flights", marshaller.supports(Flights.class));
assertTrue("CastorMarshaller does not support Flight", marshaller.supports(Flight.class));
}
@Test
public void suppressNamespacesTrue() throws Exception {
marshaller.setSuppressNamespaces(true);
String result = marshalFlights();
assertThat("Marshaller wrote invalid result", result, isSimilarTo(SUPPRESSED_NAMESPACE_EXPECTED_STRING));
}
@Test
public void suppressNamespacesFalse() throws Exception {
marshaller.setSuppressNamespaces(false);
String result = marshalFlights();
assertThat("Marshaller wrote invalid result", result, isSimilarTo(EXPECTED_STRING));
}
@Test
public void suppressXsiTypeTrue() throws Exception {
CastorObject castorObject = createCastorObject();
marshaller.setSuppressXsiType(true);
marshaller.setRootElement("objects");
String result = marshal(Arrays.asList(castorObject));
assertThat("Marshaller wrote invalid result", result, isSimilarTo(SUPPRESSED_XSI_EXPECTED_STRING));
}
@Test
public void suppressXsiTypeFalse() throws Exception {
CastorObject castorObject = createCastorObject();
marshaller.setSuppressXsiType(false);
marshaller.setRootElement("objects");
String result = marshal(Arrays.asList(castorObject));
assertThat("Marshaller wrote invalid result", result, isSimilarTo(XSI_EXPECTED_STRING));
}
@Test
public void marshalAsDocumentTrue() throws Exception {
marshaller.setMarshalAsDocument(true);
String result = marshalFlights();
assertThat("Marshaller wrote invalid result", result, isSimilarTo(DOCUMENT_EXPECTED_STRING));
assertTrue("Result doesn't contain xml declaration.",
result.contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
}
@Test
public void marshalAsDocumentFalse() throws Exception {
marshaller.setMarshalAsDocument(true);
String result = marshalFlights();
assertThat("Marshaller wrote invalid result", result, isSimilarTo(EXPECTED_STRING));
assertFalse("Result contains xml declaration.", result.matches("<\\?\\s*xml"));
}
@Test
public void rootElement() throws Exception {
marshaller.setRootElement("canceledFlights");
String result = marshalFlights();
assertThat("Marshaller wrote invalid result", result, isSimilarTo(ROOT_ELEMENT_EXPECTED_STRING));
}
@Test
public void noNamespaceSchemaLocation() throws Exception {
String noNamespaceSchemaLocation = "flights.xsd";
marshaller.setNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
String result = marshalFlights();
assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.",
noNamespaceSchemaLocation, "/tns:flights/@xsi:noNamespaceSchemaLocation", result);
assertThat("Marshaller wrote invalid result", result, isSimilarTo(EXPECTED_STRING));
}
@Test
public void schemaLocation() throws Exception {
String schemaLocation = "flights.xsd";
marshaller.setSchemaLocation(schemaLocation);
String result = marshalFlights();
assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.",
schemaLocation, "/tns:flights/@xsi:schemaLocation", result);
assertThat("Marshaller wrote invalid result", result, isSimilarTo(EXPECTED_STRING));
}
@Test
public void useXsiTypeAsRootTrue() throws Exception {
CastorObject castorObject = createCastorObject();
marshaller.setSuppressXsiType(false);
marshaller.setUseXSITypeAtRoot(true);
marshaller.setRootElement("objects");
String result = marshal(Arrays.asList(castorObject));
assertThat("Marshaller wrote invalid result", result, isSimilarTo(ROOT_WITH_XSI_EXPECTED_STRING));
}
@Test
public void useXsiTypeAsRootFalse() throws Exception {
CastorObject castorObject = createCastorObject();
marshaller.setSuppressXsiType(false);
marshaller.setUseXSITypeAtRoot(false);
marshaller.setRootElement("objects");
String result = marshal(Arrays.asList(castorObject));
assertThat("Marshaller wrote invalid result", result, isSimilarTo(ROOT_WITHOUT_XSI_EXPECTED_STRING));
}
private String marshal(Object object) throws Exception {
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
marshaller.marshal(object, result);
return writer.toString();
}
private String marshalFlights() throws Exception {
return marshal(flights);
}
/**
* Assert the values of xpath expression evaluation is exactly the same as expected value.
* <p>The xpath may contain the xml namespace prefixes, since namespaces from flight example
* are being registered.
* @param msg the error message that will be used in case of test failure
* @param expected the expected value
* @param xpath the xpath to evaluate
* @param xmlDoc the xml to use
* @throws Exception if any error occurs during xpath evaluation
*/
private void assertXpathEvaluatesTo(String msg, String expected, String xpath, String xmlDoc) throws Exception {
Map<String, String> namespaces = new HashMap<>();
namespaces.put("tns", "http://samples.springframework.org/flight");
namespaces.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
JAXPXPathEngine engine = new JAXPXPathEngine();
engine.setNamespaceContext(namespaces);
Source source = Input.fromString(xmlDoc).build();
Iterable<Node> nodeList = engine.selectNodes(xpath, source);
assertEquals(msg, expected, nodeList.iterator().next().getNodeValue());
}
/**
* Create an instance of {@link CastorObject} for testing.
*/
private CastorObject createCastorObject() {
CastorObject castorObject = new CastorObject();
castorObject.setName("test");
castorObject.setValue(8);
return castorObject;
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.castor;
/**
* Represents a POJO used by {@link CastorMarshallerTests} for testing the marshaller output.
*
* @author Jakub Narloch
*/
public class CastorObject {
private String name;
private Integer value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}

View File

@ -1,260 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.oxm.castor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.concurrent.atomic.AtomicReference;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import org.junit.Ignore;
import org.junit.Test;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.AbstractUnmarshallerTests;
import org.springframework.oxm.MarshallingException;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
* @author Jakub Narloch
* @author Sam Brannen
*/
@Deprecated
public class CastorUnmarshallerTests extends AbstractUnmarshallerTests<CastorMarshaller> {
/**
* Represents the xml with additional attribute that is not mapped in Castor config.
*/
protected static final String EXTRA_ATTRIBUTES_STRING =
"<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
"<tns:flight status=\"canceled\"><tns:number>42</tns:number></tns:flight></tns:flights>";
/**
* Represents the xml with additional element that is not mapped in Castor config.
*/
protected static final String EXTRA_ELEMENTS_STRING =
"<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
"<tns:flight><tns:number>42</tns:number><tns:date>2011-06-14</tns:date>" +
"</tns:flight></tns:flights>";
@Override
protected CastorMarshaller createUnmarshaller() throws Exception {
CastorMarshaller marshaller = new CastorMarshaller();
ClassPathResource mappingLocation = new ClassPathResource("mapping.xml", CastorMarshaller.class);
marshaller.setMappingLocation(mappingLocation);
marshaller.afterPropertiesSet();
return marshaller;
}
@Override
protected void testFlights(Object o) {
Flights flights = (Flights) o;
assertNotNull("Flights is null", flights);
assertEquals("Invalid amount of flight elements", 1, flights.getFlightCount());
testFlight(flights.getFlight()[0]);
}
@Override
protected void testFlight(Object o) {
Flight flight = (Flight) o;
assertNotNull("Flight is null", flight);
assertThat("Number is invalid", flight.getNumber(), equalTo(42L));
}
@Test
public void unmarshalTargetClass() throws Exception {
CastorMarshaller unmarshaller = new CastorMarshaller();
unmarshaller.setTargetClasses(Flights.class);
unmarshaller.afterPropertiesSet();
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8")));
Object flights = unmarshaller.unmarshal(source);
testFlights(flights);
}
@Test
public void setBothTargetClassesAndMapping() throws IOException {
CastorMarshaller unmarshaller = new CastorMarshaller();
unmarshaller.setMappingLocation(new ClassPathResource("order-mapping.xml", CastorMarshaller.class));
unmarshaller.setTargetClasses(Order.class);
unmarshaller.afterPropertiesSet();
String xml = "<order>" +
"<order-item id=\"1\" quantity=\"15\"/>" +
"<order-item id=\"3\" quantity=\"20\"/>" +
"</order>";
Order order = (Order) unmarshaller.unmarshal(new StreamSource(new StringReader(xml)));
assertEquals("Invalid amount of items", 2, order.getOrderItemCount());
OrderItem item = order.getOrderItem(0);
assertEquals("Invalid items", "1", item.getId());
assertThat("Invalid items", item.getQuantity(), equalTo(15));
item = order.getOrderItem(1);
assertEquals("Invalid items", "3", item.getId());
assertThat("Invalid items", item.getQuantity(), equalTo(20));
}
@Test
public void whitespacePreserveTrue() throws Exception {
unmarshaller.setWhitespacePreserve(true);
Object result = unmarshalFlights();
testFlights(result);
}
@Test
public void whitespacePreserveFalse() throws Exception {
unmarshaller.setWhitespacePreserve(false);
Object result = unmarshalFlights();
testFlights(result);
}
@Test
public void ignoreExtraAttributesTrue() throws Exception {
unmarshaller.setIgnoreExtraAttributes(true);
Object result = unmarshal(EXTRA_ATTRIBUTES_STRING);
testFlights(result);
}
@Test(expected = MarshallingException.class)
public void ignoreExtraAttributesFalse() throws Exception {
unmarshaller.setIgnoreExtraAttributes(false);
unmarshal(EXTRA_ATTRIBUTES_STRING);
}
@Test
@Ignore("Not working yet")
public void ignoreExtraElementsTrue() throws Exception {
unmarshaller.setIgnoreExtraElements(true);
unmarshaller.setValidating(false);
Object result = unmarshal(EXTRA_ELEMENTS_STRING);
testFlights(result);
}
@Test(expected = MarshallingException.class)
public void ignoreExtraElementsFalse() throws Exception {
unmarshaller.setIgnoreExtraElements(false);
unmarshal(EXTRA_ELEMENTS_STRING);
}
@Test
public void rootObject() throws Exception {
Flights flights = new Flights();
unmarshaller.setRootObject(flights);
Object result = unmarshalFlights();
testFlights(result);
assertSame("Result Flights is different object.", flights, result);
}
@Test
public void clearCollectionsTrue() throws Exception {
Flights flights = new Flights();
flights.setFlight(new Flight[]{new Flight()});
unmarshaller.setRootObject(flights);
unmarshaller.setClearCollections(true);
Object result = unmarshalFlights();
assertSame("Result Flights is different object.", flights, result);
assertEquals("Result Flights has incorrect number of Flight.", 1, ((Flights) result).getFlightCount());
testFlights(result);
}
@Test
public void clearCollectionsFalse() throws Exception {
Flights flights = new Flights();
flights.setFlight(new Flight[] {new Flight(), null});
unmarshaller.setRootObject(flights);
unmarshaller.setClearCollections(false);
Object result = unmarshalFlights();
assertSame("Result Flights is different object.", flights, result);
assertEquals("Result Flights has incorrect number of Flights.", 3, ((Flights) result).getFlightCount());
assertNull("Null Flight was expected.", flights.getFlight()[1]);
testFlight(flights.getFlight()[2]);
}
@Test
public void unmarshalStreamSourceWithXmlOptions() throws Exception {
final AtomicReference<XMLReader> result = new AtomicReference<>();
CastorMarshaller marshaller = new CastorMarshaller() {
@Override
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) {
result.set(xmlReader);
return null;
}
};
// 1. external-general-entities and dtd support disabled (default)
marshaller.unmarshal(new StreamSource("1"));
assertNotNull(result.get());
assertEquals(true, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl"));
assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities"));
// 2. external-general-entities and dtd support enabled
result.set(null);
marshaller.setSupportDtd(true);
marshaller.setProcessExternalEntities(true);
marshaller.unmarshal(new StreamSource("1"));
assertNotNull(result.get());
assertEquals(false, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl"));
assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities"));
}
@Test
public void unmarshalSaxSourceWithXmlOptions() throws Exception {
final AtomicReference<XMLReader> result = new AtomicReference<>();
CastorMarshaller marshaller = new CastorMarshaller() {
@Override
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) {
result.set(xmlReader);
return null;
}
};
// 1. external-general-entities and dtd support disabled (default)
marshaller.unmarshal(new SAXSource(new InputSource("1")));
assertNotNull(result.get());
assertEquals(true, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl"));
assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities"));
// 2. external-general-entities and dtd support enabled
result.set(null);
marshaller.setSupportDtd(true);
marshaller.setProcessExternalEntities(true);
marshaller.unmarshal(new SAXSource(new InputSource("1")));
assertNotNull(result.get());
assertEquals(false, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl"));
assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities"));
}
private Object unmarshalFlights() throws Exception {
return unmarshal(INPUT_STRING);
}
private Object unmarshal(String xml) throws Exception {
StreamSource source = new StreamSource(new StringReader(xml));
return unmarshaller.unmarshal(source);
}
}

View File

@ -1,31 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">
<mapping>
<description>Castor generated mapping file</description>
<class name="org.springframework.oxm.castor.Flights">
<description>
Default mapping for class
org.springframework.oxm.castor.Flights
</description>
<map-to xml="flights"
ns-uri="http://samples.springframework.org/flight" ns-prefix="tns"/>
<field name="flight"
type="org.springframework.oxm.castor.Flight"
required="true" collection="array">
<bind-xml name="tns:flight" node="element" QName-prefix="tns"
xmlns:tns="http://samples.springframework.org/flight"/>
</field>
</class>
<class name="org.springframework.oxm.castor.Flight">
<description>
Default mapping for class
org.springframework.oxm.castor.Flight
</description>
<map-to xml="flight"
ns-uri="http://samples.springframework.org/flight" ns-prefix="tns"/>
<field name="number" type="long" required="true">
<bind-xml name="tns:number" node="element"
xmlns:tns="http://samples.springframework.org/flight"/>
</field>
</class>
</mapping>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<mapping>
<class name="org.springframework.oxm.castor.OrderItem">
<field name="Id" type="java.lang.String">
<bind-xml name="id" node="attribute" />
</field>
<field name="Quantity" type="java.lang.Integer">
<bind-xml name="quantity" node="attribute" />
</field>
</class>
</mapping>

View File

@ -12,15 +12,4 @@
<oxm:class-to-be-bound name="org.springframework.oxm.jaxb.test.FlightType"/>
</oxm:jaxb2-marshaller>
<!-- Castor -->
<oxm:castor-marshaller id="castorEncodingMarshaller" encoding="ISO-8859-1"/>
<oxm:castor-marshaller id="castorTargetClassMarshaller" target-class="org.springframework.oxm.castor.Flight"/>
<oxm:castor-marshaller id="castorTargetPackageMarshaller" target-package="org.springframework.oxm.castor"/>
<oxm:castor-marshaller id="castorMappingLocationMarshaller"
mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>
</beans>

View File

@ -6159,7 +6159,7 @@ Spring's O-X mapping operates through two global interfaces: {api-spring-framewo
with relative ease, with little or no change required on the classes that do the
marshalling. This approach has the additional benefit of making it possible to do XML
marshalling with a mix-and-match approach (for example, some marshalling performed using JAXB
and some by Castor) in a non-intrusive fashion, letting you use the strength of each
and some by XStream) in a non-intrusive fashion, letting you use the strength of each
technology.
@ -6383,18 +6383,18 @@ can do so by using the following `applicationContext.xml`:
----
<beans>
<bean id="application" class="Application">
<property name="marshaller" ref="castorMarshaller" />
<property name="unmarshaller" ref="castorMarshaller" />
<property name="marshaller" ref="xstreamMarshaller" />
<property name="unmarshaller" ref="xstreamMarshaller" />
</bean>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</beans>
----
This application context uses Castor, but we could have used any of the other marshaller
instances described later in this chapter. Note that, by default, Castor does not require any further
This application context uses XStream, but we could have used any of the other marshaller
instances described later in this chapter. Note that, by default, XStream does not require any further
configuration, so the bean definition is rather simple. Also note that the
`CastorMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the
`castorMarshaller` bean in both the `marshaller` and `unmarshaller` property of the
`XStreamMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the
`xstreamMarshaller` bean in both the `marshaller` and `unmarshaller` property of the
application.
This sample application produces the following `settings.xml` file:
@ -6430,11 +6430,10 @@ preamble of the XML configuration file. The following example shows how to do so
<2> Specify the `oxm` schema location.
Currently, the schema makes the following elements available:
The schema makes the following elements available:
* <<oxm-jaxb2-xsd, `jaxb2-marshaller`>>
* <<oxm-jibx-xsd, `jibx-marshaller`>>
* <<oxm-castor-xsd, `castor-marshaller`>>
Each tag is explained in its respective marshaller's section. As an example, though,
the configuration of a JAXB2 marshaller might resemble the following:
@ -6530,105 +6529,6 @@ The following table describes the available attributes:
[[oxm-castor]]
=== Castor
Castor XML mapping is an open source XML binding framework. It lets you transform
the data contained in a Java object model to and from an XML document. By default, it does
not require any further configuration, though you can use a mapping file to have more
control over the behavior of Castor.
For more information on Castor, see the
http://castor-data-binding.github.io/castor[Castor web site]. The Spring
integration classes reside in the `org.springframework.oxm.castor` package.
[[oxm-castor-marshaller]]
==== Using `CastorMarshaller`
As with JAXB, the `CastorMarshaller` implements both the `Marshaller` and `Unmarshaller`
interface. It can be wired up as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
...
</beans>
----
[[oxm-castor-mapping]]
==== Mapping
Although it is possible to rely on Castor's default marshalling behavior, it might be
necessary to have more control over it. You can get more control by using a Castor mapping
file. For more information, see http://castor-data-binding.github.io/castor/reference-guides/1.3.3/html-single/index.html#xml.mapping[Castor
XML Mapping].
You can set the mapping by using the `mappingLocation` resource property, indicated in the following example
with a classpath resource:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
----
[[oxm-castor-xsd]]
===== XML Configuration Namespace
The `castor-marshaller` tag configures a
`org.springframework.oxm.castor.CastorMarshaller`, as the following example shows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>
----
You can configure the marshaller instance in two ways: by specifying either the location
of a mapping file (through the `mapping-location` property) or by identifying Java
POJOs (through the `target-class` or `target-package` properties) for which there exist
corresponding XML descriptor classes. The latter way is usually used in conjunction with
XML code generation from XML schemas.
The following table describes the available attributes:
|===
| Attribute| Description| Required
| `id`
| The ID of the marshaller
| No
| `encoding`
| The encoding to use for unmarshalling from XML
| No
| `target-class`
| A Java class name for a POJO for which an XML class descriptor is available (as
generated through code generation)
| No
| `target-package`
| A Java package name that identifies a package that contains POJOs and their
corresponding Castor XML descriptor classes (as generated through code generation from
XML schemas)
| No
| `mapping-location`
| Location of a Castor XML mapping file
| No
|===
[[oxm-jibx]]
=== JiBX

View File

@ -1902,7 +1902,7 @@ details of how it is represented as a JMS message.
The sandbox currently includes a `MapMessageConverter`, which uses reflection to convert
between a JavaBean and a `MapMessage`. Other popular implementation choices you might
implement yourself are converters that use an existing XML marshalling package (such as
JAXB, Castor, or XStream) to create a `TextMessage` that represents the object.
JAXB or XStream) to create a `TextMessage` that represents the object.
To accommodate the setting of a message's properties, headers, and body that can not be
generically encapsulated inside a converter class, the `MessagePostProcessor` interface