Rename modules {org.springframework.*=>spring-*}
This renaming more intuitively expresses the relationship between
subprojects and the JAR artifacts they produce.
Tracking history across these renames is possible, but it requires
use of the --follow flag to `git log`, for example
$ git log spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history up until the renaming event, where
$ git log --follow spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history for all changes to the file, before and after the
renaming.
See http://chrisbeams.com/git-diff-across-renamed-directories
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link Marshaller} that has support for Java 5 generics.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @sicne 3.0.1
|
||||
*/
|
||||
public interface GenericMarshaller extends Marshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this marshaller can marshal instances of the supplied generic type.
|
||||
* @param genericType the type that this marshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied type;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Type genericType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link Unmarshaller} that has support for Java 5 generics.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @sicne 3.0.1
|
||||
*/
|
||||
public interface GenericUnmarshaller extends Unmarshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this marshaller can marshal instances of the supplied generic type.
|
||||
* @param genericType the type that this marshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied type;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Type genericType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Result;
|
||||
|
||||
/**
|
||||
* Defines the contract for Object XML Mapping Marshallers. Implementations of this interface
|
||||
* can serialize a given Object to an XML Stream.
|
||||
*
|
||||
* <p>Although the <code>marshal</code> method accepts a <code>java.lang.Object</code> as its
|
||||
* first parameter, most <code>Marshaller</code> implementations cannot handle arbitrary
|
||||
* <code>Object</code>s. Instead, a object class must be registered with the marshaller,
|
||||
* or have a common base class.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see Unmarshaller
|
||||
*/
|
||||
public interface Marshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this marshaller can marshal instances of the supplied type.
|
||||
* @param clazz the class that this marshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied class;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Marshals the object graph with the given root into the provided {@link Result}.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param result the result to marshal to
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
*/
|
||||
void marshal(Object graph, Result result) throws IOException, XmlMappingException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
/**
|
||||
* Base class for exception thrown when a marshalling or unmarshalling error occurs.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see MarshallingFailureException
|
||||
* @see UnmarshallingFailureException
|
||||
*/
|
||||
public abstract class MarshallingException extends XmlMappingException {
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingException</code> with the specified detail message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
protected MarshallingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
protected MarshallingException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
/**
|
||||
* Exception thrown on marshalling failure.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MarshallingFailureException extends MarshallingException {
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingFailureException</code> with the specified detail message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public MarshallingFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingFailureException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public MarshallingFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
/**
|
||||
* Exception that indicates that the cause cannot be distinguished further.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class UncategorizedMappingException extends XmlMappingException {
|
||||
|
||||
/**
|
||||
* Construct an <code>UncategorizedMappingException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public UncategorizedMappingException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
/**
|
||||
* Defines the contract for Object XML Mapping unmarshallers. Implementations of this
|
||||
* interface can deserialize a given XML Stream to an Object graph.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see Marshaller
|
||||
*/
|
||||
public interface Unmarshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this unmarshaller can unmarshal instances of the supplied type.
|
||||
* @param clazz the class that this unmarshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this unmarshaller can indeed unmarshal to the supplied class;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Unmarshals the given {@link Source} into an object graph.
|
||||
* @param source the source to marshal from
|
||||
* @return the object graph
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
*/
|
||||
Object unmarshal(Source source) throws IOException, XmlMappingException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
/**
|
||||
* Exception thrown on unmarshalling failure.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class UnmarshallingFailureException extends MarshallingException {
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingFailureException</code> with the specified detail message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public UnmarshallingFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a <code>MarshallingFailureException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public UnmarshallingFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
/**
|
||||
* Exception thrown on marshalling validation failure.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ValidationFailureException extends XmlMappingException {
|
||||
|
||||
/**
|
||||
* Construct a <code>ValidationFailureException</code> with the specified detail message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public ValidationFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a <code>ValidationFailureException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public ValidationFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* Root of the hierarchy of Object XML Mapping exceptions.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class XmlMappingException extends NestedRuntimeException {
|
||||
|
||||
/**
|
||||
* Construct an <code>XmlMappingException</code> with the specified detail message.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public XmlMappingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an <code>XmlMappingException</code> with the specified detail message
|
||||
* and nested exception.
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public XmlMappingException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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
|
||||
*/
|
||||
public class CastorMappingException extends XmlMappingException {
|
||||
|
||||
/**
|
||||
* Construct a <code>CastorMappingException</code> 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,684 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.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.XMLContext;
|
||||
import org.exolab.castor.xml.XMLException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
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.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.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>Marshaller</code> 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</code>, the <code>CastorMarshaller</code> 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</code>.
|
||||
*
|
||||
* <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</code>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Jakub Narloch
|
||||
* @see #setEncoding(String)
|
||||
* @see #setTargetClass(Class)
|
||||
* @see #setTargetPackages(String[])
|
||||
* @see #setMappingLocation(Resource)
|
||||
* @see #setMappingLocations(Resource[])
|
||||
* @since 3.0
|
||||
*/
|
||||
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";
|
||||
|
||||
private Resource[] mappingLocations;
|
||||
|
||||
private String encoding = DEFAULT_ENCODING;
|
||||
|
||||
private Class[] targetClasses;
|
||||
|
||||
private String[] targetPackages;
|
||||
|
||||
private boolean validating = false;
|
||||
|
||||
private boolean whitespacePreserve = false;
|
||||
|
||||
private boolean ignoreExtraAttributes = true;
|
||||
|
||||
private boolean ignoreExtraElements = false;
|
||||
|
||||
private Map<String, String> namespaceMappings;
|
||||
|
||||
private XMLContext xmlContext;
|
||||
|
||||
private boolean suppressNamespaces = false;
|
||||
|
||||
private boolean suppressXsiType = false;
|
||||
|
||||
private boolean marshalAsDocument = true;
|
||||
|
||||
private String rootElement;
|
||||
|
||||
private boolean marshalExtendedType = true;
|
||||
|
||||
private String noNamespaceSchemaLocation;
|
||||
|
||||
private String schemaLocation;
|
||||
|
||||
private boolean useXSITypeAtRoot = false;
|
||||
|
||||
private Map<String, String> processingInstructions;
|
||||
|
||||
private Map<String, String> namespaceToPackageMapping;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private Object root;
|
||||
|
||||
private boolean reuseObjects = false;
|
||||
|
||||
private boolean clearCollections = false;
|
||||
|
||||
/**
|
||||
* Set the encoding to be used for stream access.
|
||||
*
|
||||
* @see #DEFAULT_ENCODING
|
||||
*/
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = 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. Alternative means of configuring <code>CastorMarshaller<code> for unmarshalling
|
||||
* multiple classes include use of mapping files, and specifying packages with Castor descriptor classes.
|
||||
*/
|
||||
public void setTargetClass(Class targetClass) {
|
||||
this.targetClasses = new Class[]{targetClass};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Castor target classes. Alternative means of configuring <code>CastorMarshaller<code> 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 names of 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</code>.
|
||||
*
|
||||
* @see Marshaller#setValidation(boolean)
|
||||
*/
|
||||
public void setValidating(boolean validating) {
|
||||
this.validating = validating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the Castor {@link Unmarshaller} should preserve "ignorable" whitespace. <p>Default is
|
||||
* <code>false</code>.
|
||||
*
|
||||
* @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</code>: 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</code>, extra attributes are flagged as an error.
|
||||
*
|
||||
* @see org.exolab.castor.xml.Unmarshaller#setIgnoreExtraElements(boolean)
|
||||
*/
|
||||
public void setIgnoreExtraElements(boolean ignoreExtraElements) {
|
||||
this.ignoreExtraElements = ignoreExtraElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this marshaller should output namespaces.
|
||||
*/
|
||||
public boolean isSuppressNamespaces() {
|
||||
return suppressNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this marshaller should output namespaces. 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this marshaller should output the xsi:type attribute.
|
||||
*/
|
||||
public boolean isSuppressXsiType() {
|
||||
return suppressXsiType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this marshaller should output the {@code xsi:type} attribute. 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the root element.
|
||||
*
|
||||
* @see org.exolab.castor.xml.Marshaller#setRootElement(String)
|
||||
*/
|
||||
public void setRootElement(String rootElement) {
|
||||
this.rootElement = rootElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected object for the unmarshaller, into which the source will be unmarshalled.
|
||||
*
|
||||
* @see org.exolab.castor.xml.Unmarshaller#setObject(Object)
|
||||
*/
|
||||
public void setObject(Object root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this unmarshaller should re-use objects. This will be only used when unmarshalling to existing
|
||||
* object. </p> The default is {@link 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 {@link 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;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() throws CastorMappingException, IOException {
|
||||
if (logger.isInfoEnabled()) {
|
||||
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 (!ObjectUtils.isEmpty(this.targetPackages)) {
|
||||
logger.info(
|
||||
"Configured for target packages [" + StringUtils.arrayToCommaDelimitedString(targetPackages) +
|
||||
"]");
|
||||
}
|
||||
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.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</code>. 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(Resource[] mappingLocations, Class[] targetClasses, 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);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> for all classes, i.e. Castor supports arbitrary classes.
|
||||
*/
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Marshalling
|
||||
|
||||
@Override
|
||||
protected final void marshalDomNode(Object graph, Node node) throws XmlMappingException {
|
||||
marshalSaxHandlers(graph, DomUtils.createContentHandler(node), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
|
||||
throws XmlMappingException {
|
||||
Marshaller marshaller = xmlContext.createMarshaller();
|
||||
marshaller.setContentHandler(contentHandler);
|
||||
marshal(graph, marshaller);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalOutputStream(Object graph, OutputStream outputStream)
|
||||
throws XmlMappingException, IOException {
|
||||
marshalWriter(graph, new OutputStreamWriter(outputStream, encoding));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
|
||||
Marshaller marshaller = xmlContext.createMarshaller();
|
||||
marshaller.setWriter(writer);
|
||||
marshal(graph, marshaller);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException {
|
||||
marshalSaxHandlers(graph, StaxUtils.createContentHandler(eventWriter), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
|
||||
marshalSaxHandlers(graph, StaxUtils.createContentHandler(streamWriter), null);
|
||||
}
|
||||
|
||||
private void marshal(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}.
|
||||
*
|
||||
* </p>The default implementation invokes
|
||||
* <ol>
|
||||
* <li>{@link Marshaller#setValidation(boolean)},</li>
|
||||
* <li>{@link Marshaller#setSuppressNamespaces(boolean)},</li>
|
||||
* <li>{@link Marshaller#setSuppressXSIType(boolean)}, </li>
|
||||
* <li>{@link Marshaller#setMarshalAsDocument(boolean)}, </li>
|
||||
* <li>{@link Marshaller#setRootElement(String)},</li>
|
||||
* <li>{@link Marshaller#setMarshalExtendedType(boolean)},</li>
|
||||
* <li>{@link Marshaller#setNoNamespaceSchemaLocation(String)},</li>
|
||||
* <li>{@link Marshaller#setSchemaLocation(String)} and</li>
|
||||
* <li>{@link Marshaller#setUseXSITypeAtRoot(boolean)}.</li>
|
||||
* </ol>
|
||||
* with the property set on this marshaller.
|
||||
* It also calls {@link Marshaller#setNamespaceMapping(String, String)}
|
||||
* with the {@linkplain #setNamespaceMappings(java.util.Map) namespace mappings} and
|
||||
* {@link Marshaller#addProcessingInstruction(String, String)} with the
|
||||
* {@linkplain #setProcessingInstructions(java.util.Map) processing instructions}.
|
||||
*/
|
||||
protected void customizeMarshaller(Marshaller marshaller) {
|
||||
marshaller.setValidation(this.validating);
|
||||
marshaller.setSuppressNamespaces(isSuppressNamespaces());
|
||||
marshaller.setSuppressXSIType(isSuppressXsiType());
|
||||
marshaller.setMarshalAsDocument(marshalAsDocument);
|
||||
marshaller.setRootElement(rootElement);
|
||||
marshaller.setMarshalExtendedType(marshalExtendedType);
|
||||
marshaller.setNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
|
||||
marshaller.setSchemaLocation(schemaLocation);
|
||||
marshaller.setUseXSITypeAtRoot(useXSITypeAtRoot);
|
||||
if (processingInstructions != null) {
|
||||
for (Map.Entry<String, String> processingInstruction : processingInstructions.entrySet()) {
|
||||
marshaller.addProcessingInstruction(processingInstruction.getKey(), processingInstruction.getValue());
|
||||
}
|
||||
}
|
||||
if (this.namespaceMappings != null) {
|
||||
for (Map.Entry<String, String> entry : namespaceMappings.entrySet()) {
|
||||
marshaller.setNamespaceMapping(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalDomNode(Node node) throws XmlMappingException {
|
||||
try {
|
||||
return createUnmarshaller().unmarshal(node);
|
||||
}
|
||||
catch (XMLException ex) {
|
||||
throw convertCastorException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
|
||||
try {
|
||||
return createUnmarshaller().unmarshal(new InputSource(inputStream));
|
||||
}
|
||||
catch (XMLException ex) {
|
||||
throw convertCastorException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
|
||||
try {
|
||||
return createUnmarshaller().unmarshal(new InputSource(reader));
|
||||
}
|
||||
catch (XMLException ex) {
|
||||
throw convertCastorException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final 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 final Object unmarshalXmlEventReader(XMLEventReader eventReader) {
|
||||
try {
|
||||
return createUnmarshaller().unmarshal(eventReader);
|
||||
}
|
||||
catch (XMLException ex) {
|
||||
throw convertCastorException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalXmlStreamReader(XMLStreamReader streamReader) {
|
||||
try {
|
||||
return createUnmarshaller().unmarshal(streamReader);
|
||||
}
|
||||
catch (XMLException ex) {
|
||||
throw convertCastorException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Unmarshaller createUnmarshaller() {
|
||||
Unmarshaller unmarshaller = this.xmlContext.createUnmarshaller();
|
||||
customizeUnmarshaller(unmarshaller);
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that allows for customizing of the given Castor {@link Unmarshaller}.
|
||||
*
|
||||
* </p> The default implementation invokes
|
||||
* <ol>
|
||||
* <li>{@link Unmarshaller#setValidation(boolean)},
|
||||
* <li>{@link Unmarshaller#setWhitespacePreserve(boolean)},
|
||||
* <li>{@link Unmarshaller#setIgnoreExtraAttributes(boolean)},
|
||||
* <li>{@link Unmarshaller#setIgnoreExtraElements(boolean)},
|
||||
* <li>{@link Unmarshaller#setClassLoader(ClassLoader)},
|
||||
* <li>{@link Unmarshaller#setObject(Object)},
|
||||
* <li>{@link Unmarshaller#setReuseObjects(boolean)} and
|
||||
* <li>{@link Unmarshaller#setClearCollections(boolean)}
|
||||
* </ol>
|
||||
* with the properties set on this marshaller.
|
||||
* It also calls {@link Unmarshaller#addNamespaceToPackageMapping(String, String)} with the
|
||||
* {@linkplain #setNamespaceMappings(java.util.Map) namespace to package mapping}.
|
||||
*/
|
||||
protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
|
||||
unmarshaller.setValidation(this.validating);
|
||||
unmarshaller.setWhitespacePreserve(this.whitespacePreserve);
|
||||
unmarshaller.setIgnoreExtraAttributes(this.ignoreExtraAttributes);
|
||||
unmarshaller.setIgnoreExtraElements(this.ignoreExtraElements);
|
||||
unmarshaller.setClassLoader(classLoader);
|
||||
unmarshaller.setObject(root);
|
||||
unmarshaller.setReuseObjects(reuseObjects);
|
||||
unmarshaller.setClearCollections(clearCollections);
|
||||
if (namespaceToPackageMapping != null) {
|
||||
for (Map.Entry<String, String> mapping : namespaceToPackageMapping.entrySet()) {
|
||||
unmarshaller.addNamespaceToPackageMapping(mapping.getKey(), mapping.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given <code>XMLException</code> to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> 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 Castor <code>XMLException</code> that occurred
|
||||
* @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>), or unmarshalling
|
||||
* (<code>false</code>)
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package providing integration of <a href="http://www.castor.org/xml-mapping.html">Castor</a> within Springs O/X Mapping
|
||||
* support
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.castor;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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/></code> element.
|
||||
*
|
||||
* @author Jakub Narloch
|
||||
* @since 3.1
|
||||
*/
|
||||
public class CastorMarshallerBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
private static final String CASTOR_MARSHALLER_CLASS_NAME = "org.springframework.oxm.castor.CastorMarshaller";
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return CASTOR_MARSHALLER_CLASS_NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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 java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <code><oxm:jaxb2-marshaller/> element.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
class Jaxb2MarshallerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private static final String JAXB2_MARSHALLER_CLASS_NAME = "org.springframework.oxm.jaxb.Jaxb2Marshaller";
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return JAXB2_MARSHALLER_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder beanDefinitionBuilder) {
|
||||
String contextPath = element.getAttribute("contextPath");
|
||||
if (StringUtils.hasText(contextPath)) {
|
||||
beanDefinitionBuilder.addPropertyValue("contextPath", contextPath);
|
||||
}
|
||||
List classes = DomUtils.getChildElementsByTagName(element, "class-to-be-bound");
|
||||
if (!classes.isEmpty()) {
|
||||
ManagedList classesToBeBound = new ManagedList(classes.size());
|
||||
for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
|
||||
Element classToBeBound = (Element) iterator.next();
|
||||
String className = classToBeBound.getAttribute("name");
|
||||
classesToBeBound.add(className);
|
||||
}
|
||||
beanDefinitionBuilder.addPropertyValue("classesToBeBound", classesToBeBound);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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:jibx-marshaller/> element.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
class JibxMarshallerBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
private static final String JIBX_MARSHALLER_CLASS_NAME = "org.springframework.oxm.jibx.JibxMarshaller";
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return JIBX_MARSHALLER_CLASS_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* {@link NamespaceHandler} for the '<code>oxm</code>' namespace.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class OxmNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("jaxb2-marshaller", new Jaxb2MarshallerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("jibx-marshaller", new JibxMarshallerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("xmlbeans-marshaller", new XmlBeansMarshallerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("castor-marshaller", new CastorMarshallerBeanDefinitionParser());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <code><oxm:xmlbeans-marshaller/> element.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
class XmlBeansMarshallerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
public static final String XML_BEANS_MARSHALLER_CLASS_NAME = "org.springframework.oxm.xmlbeans.XmlBeansMarshaller";
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return XML_BEANS_MARSHALLER_CLASS_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder beanDefinitionBuilder) {
|
||||
String optionsName = element.getAttribute("options");
|
||||
if (StringUtils.hasText(optionsName)) {
|
||||
beanDefinitionBuilder.addPropertyReference("xmlOptions", optionsName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides an namespace handler for the Spring Object/XML namespace
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.config;
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jaxb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlEnum;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlSeeAlso;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.oxm.UncategorizedMappingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Helper class for {@link Jaxb2Marshaller} that scans given packages for classes marked with JAXB2 annotations.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author David Harrigan
|
||||
* @see #scanPackages()
|
||||
*/
|
||||
class ClassPathJaxb2TypeScanner {
|
||||
|
||||
private static final String RESOURCE_PATTERN = "/**/*.class";
|
||||
|
||||
private final TypeFilter[] jaxb2TypeFilters =
|
||||
new TypeFilter[]{new AnnotationTypeFilter(XmlRootElement.class, false),
|
||||
new AnnotationTypeFilter(XmlType.class, false), new AnnotationTypeFilter(XmlSeeAlso.class, false),
|
||||
new AnnotationTypeFilter(XmlEnum.class, false)};
|
||||
|
||||
private final String[] packagesToScan;
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
private List<Class<?>> jaxb2Classes = new ArrayList<Class<?>>();
|
||||
|
||||
/** Constructs a new {@code ClassPathJaxb2TypeScanner} for the given packages. */
|
||||
ClassPathJaxb2TypeScanner(String[] packagesToScan) {
|
||||
Assert.notEmpty(packagesToScan, "'packagesToScan' must not be empty");
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
if (resourceLoader != null) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the JAXB2 classes found in the specified packages. */
|
||||
Class<?>[] getJaxb2Classes() {
|
||||
return jaxb2Classes.toArray(new Class<?>[jaxb2Classes.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the packages for classes marked with JAXB2 annotations.
|
||||
*
|
||||
* @throws UncategorizedMappingException in case of errors
|
||||
*/
|
||||
void scanPackages() throws UncategorizedMappingException {
|
||||
try {
|
||||
for (String packageToScan : packagesToScan) {
|
||||
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(packageToScan) + RESOURCE_PATTERN;
|
||||
Resource[] resources = resourcePatternResolver.getResources(pattern);
|
||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
|
||||
for (Resource resource : resources) {
|
||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||
if (isJaxb2Class(metadataReader, metadataReaderFactory)) {
|
||||
String className = metadataReader.getClassMetadata().getClassName();
|
||||
Class<?> jaxb2AnnotatedClass = resourcePatternResolver.getClassLoader().loadClass(className);
|
||||
jaxb2Classes.add(jaxb2AnnotatedClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncategorizedMappingException("Failed to scan classpath for unlisted classes", ex);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new UncategorizedMappingException("Failed to load annotated classes from classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isJaxb2Class(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
|
||||
for (TypeFilter filter : jaxb2TypeFilters) {
|
||||
if (filter.match(reader, factory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,902 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jaxb;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.MarshalException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.UnmarshalException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.ValidationEventHandler;
|
||||
import javax.xml.bind.ValidationException;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.bind.attachment.AttachmentUnmarshaller;
|
||||
import javax.xml.datatype.Duration;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.ls.LSResourceResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.oxm.GenericMarshaller;
|
||||
import org.springframework.oxm.GenericUnmarshaller;
|
||||
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.mime.MimeContainer;
|
||||
import org.springframework.oxm.mime.MimeMarshaller;
|
||||
import org.springframework.oxm.mime.MimeUnmarshaller;
|
||||
import org.springframework.oxm.support.SaxResourceUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
|
||||
*
|
||||
* <p>The typical usage will be to set either the <code>contextPath</code> or the <code>classesToBeBound</code> property
|
||||
* on this bean, possibly customize the marshaller and unmarshaller by setting properties, schemas, adapters, and
|
||||
* listeners, and to refer to it.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see #setContextPath(String)
|
||||
* @see #setClassesToBeBound(Class[])
|
||||
* @see #setJaxbContextProperties(Map)
|
||||
* @see #setMarshallerProperties(Map)
|
||||
* @see #setUnmarshallerProperties(Map)
|
||||
* @see #setSchema(Resource)
|
||||
* @see #setSchemas(Resource[])
|
||||
* @see #setMarshallerListener(javax.xml.bind.Marshaller.Listener)
|
||||
* @see #setUnmarshallerListener(javax.xml.bind.Unmarshaller.Listener)
|
||||
* @see #setAdapters(XmlAdapter[])
|
||||
* @since 3.0
|
||||
*/
|
||||
public class Jaxb2Marshaller
|
||||
implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller, BeanClassLoaderAware,
|
||||
ResourceLoaderAware, InitializingBean {
|
||||
|
||||
private static final String CID = "cid:";
|
||||
|
||||
|
||||
/**
|
||||
* Logger available to subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private String contextPath;
|
||||
|
||||
private Class<?>[] classesToBeBound;
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
private Map<String, ?> jaxbContextProperties;
|
||||
|
||||
private Map<String, ?> marshallerProperties;
|
||||
|
||||
private Map<String, ?> unmarshallerProperties;
|
||||
|
||||
private Marshaller.Listener marshallerListener;
|
||||
|
||||
private Unmarshaller.Listener unmarshallerListener;
|
||||
|
||||
private ValidationEventHandler validationEventHandler;
|
||||
|
||||
private XmlAdapter<?, ?>[] adapters;
|
||||
|
||||
private Resource[] schemaResources;
|
||||
|
||||
private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||
|
||||
private boolean mtomEnabled = false;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private JAXBContext jaxbContext;
|
||||
|
||||
private Schema schema;
|
||||
|
||||
private boolean lazyInit = false;
|
||||
|
||||
private boolean supportJaxbElementClass = false;
|
||||
|
||||
private LSResourceResolver schemaResourceResolver;
|
||||
|
||||
|
||||
/**
|
||||
* Set multiple JAXB context paths. The given array of context paths is converted to a
|
||||
* colon-delimited string, as supported by JAXB.
|
||||
*/
|
||||
public void setContextPaths(String... contextPaths) {
|
||||
Assert.notEmpty(contextPaths, "'contextPaths' must not be empty");
|
||||
this.contextPath = StringUtils.arrayToDelimitedString(contextPaths, ":");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JAXB context path.
|
||||
* <p>Setting this property, {@link #setClassesToBeBound "classesToBeBound"}, or
|
||||
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
*/
|
||||
public void setContextPath(String contextPath) {
|
||||
Assert.hasText(contextPath, "'contextPath' must not be null");
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JAXB context path.
|
||||
*/
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of Java classes to be recognized by a newly created JAXBContext.
|
||||
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
*/
|
||||
public void setClassesToBeBound(Class<?>... classesToBeBound) {
|
||||
Assert.notEmpty(classesToBeBound, "'classesToBeBound' must not be empty");
|
||||
this.classesToBeBound = classesToBeBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of Java classes to be recognized by a newly created JAXBContext.
|
||||
*/
|
||||
public Class<?>[] getClassesToBeBound() {
|
||||
return this.classesToBeBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the packages to search using Spring-based scanning for classes with JAXB2 annotations in the classpath.
|
||||
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||
* {@link #setClassesToBeBound "classesToBeBound"} is required. This is analogous to Spring's component-scan feature
|
||||
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||
*/
|
||||
public void setPackagesToScan(String[] packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the packages to search for JAXB2 annotations.
|
||||
*/
|
||||
public String[] getPackagesToScan() {
|
||||
return packagesToScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>JAXBContext</code> properties. These implementation-specific
|
||||
* properties will be set on the underlying <code>JAXBContext</code>.
|
||||
*/
|
||||
public void setJaxbContextProperties(Map<String, ?> jaxbContextProperties) {
|
||||
this.jaxbContextProperties = jaxbContextProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JAXB <code>Marshaller</code> properties. These properties will be set on the
|
||||
* underlying JAXB <code>Marshaller</code>, and allow for features such as indentation.
|
||||
* @param properties the properties
|
||||
* @see javax.xml.bind.Marshaller#setProperty(String,Object)
|
||||
* @see javax.xml.bind.Marshaller#JAXB_ENCODING
|
||||
* @see javax.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT
|
||||
* @see javax.xml.bind.Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
|
||||
* @see javax.xml.bind.Marshaller#JAXB_SCHEMA_LOCATION
|
||||
*/
|
||||
public void setMarshallerProperties(Map<String, ?> properties) {
|
||||
this.marshallerProperties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JAXB <code>Unmarshaller</code> properties. These properties will be set on the
|
||||
* underlying JAXB <code>Unmarshaller</code>.
|
||||
* @param properties the properties
|
||||
* @see javax.xml.bind.Unmarshaller#setProperty(String,Object)
|
||||
*/
|
||||
public void setUnmarshallerProperties(Map<String, ?> properties) {
|
||||
this.unmarshallerProperties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the <code>Marshaller.Listener</code> to be registered with the JAXB <code>Marshaller</code>.
|
||||
*/
|
||||
public void setMarshallerListener(Marshaller.Listener marshallerListener) {
|
||||
this.marshallerListener = marshallerListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>Unmarshaller.Listener</code> to be registered with the JAXB <code>Unmarshaller</code>.
|
||||
*/
|
||||
public void setUnmarshallerListener(Unmarshaller.Listener unmarshallerListener) {
|
||||
this.unmarshallerListener = unmarshallerListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JAXB validation event handler. This event handler will be called by JAXB
|
||||
* if any validation errors are encountered during calls to any of the marshal APIs.
|
||||
*/
|
||||
public void setValidationEventHandler(ValidationEventHandler validationEventHandler) {
|
||||
this.validationEventHandler = validationEventHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the <code>XmlAdapter</code>s to be registered with the JAXB <code>Marshaller</code>
|
||||
* and <code>Unmarshaller</code>
|
||||
*/
|
||||
public void setAdapters(XmlAdapter<?, ?>[] adapters) {
|
||||
this.adapters = adapters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema resource to use for validation.
|
||||
*/
|
||||
public void setSchema(Resource schemaResource) {
|
||||
this.schemaResources = new Resource[] {schemaResource};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema resources to use for validation.
|
||||
*/
|
||||
public void setSchemas(Resource[] schemaResources) {
|
||||
this.schemaResources = schemaResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema language. Default is the W3C XML Schema: <code>http://www.w3.org/2001/XMLSchema"</code>.
|
||||
* @see XMLConstants#W3C_XML_SCHEMA_NS_URI
|
||||
* @see XMLConstants#RELAXNG_NS_URI
|
||||
*/
|
||||
public void setSchemaLanguage(String schemaLanguage) {
|
||||
this.schemaLanguage = schemaLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource resolver, as used to load the schema resources.
|
||||
*
|
||||
* @see SchemaFactory#setResourceResolver(org.w3c.dom.ls.LSResourceResolver)
|
||||
* @see #setSchema(Resource)
|
||||
* @see #setSchemas(Resource[])
|
||||
*/
|
||||
public void setSchemaResourceResolver(LSResourceResolver schemaResourceResolver) {
|
||||
this.schemaResourceResolver = schemaResourceResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether MTOM support should be enabled or not.
|
||||
* Default is <code>false</code>: marshalling using XOP/MTOM not being enabled.
|
||||
*/
|
||||
public void setMtomEnabled(boolean mtomEnabled) {
|
||||
this.mtomEnabled = mtomEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to lazily initialize the {@link JAXBContext} for this marshaller.
|
||||
* Default is {@code false} to initialize on startup; can be switched to {@code true}.
|
||||
* <p>Early initialization just applies if {@link #afterPropertiesSet()} is called.
|
||||
*/
|
||||
public void setLazyInit(boolean lazyInit) {
|
||||
this.lazyInit = lazyInit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether the {@link #supports(Class)} returns {@code true} for the {@link JAXBElement} class.
|
||||
* <p>Default is {@code false}, meaning that {@code supports(Class)} always returns {@code false} for
|
||||
* {@code JAXBElement} classes (though {@link #supports(Type)} can return {@code true}, since it can obtain the
|
||||
* type parameters of {@code JAXBElement}).
|
||||
* <p>This property is typically enabled in combination with usage of classes like
|
||||
* {@link org.springframework.web.servlet.view.xml.MarshallingView MarshallingView}, since the {@code ModelAndView}
|
||||
* does not offer type parameter information at runtime.
|
||||
*
|
||||
* @see #supports(Class)
|
||||
* @see #supports(Type)
|
||||
*/
|
||||
public void setSupportJaxbElementClass(boolean supportJaxbElementClass) {
|
||||
this.supportJaxbElementClass = supportJaxbElementClass;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
boolean hasContextPath = StringUtils.hasLength(getContextPath());
|
||||
boolean hasClassesToBeBound = !ObjectUtils.isEmpty(getClassesToBeBound());
|
||||
boolean hasPackagesToScan = !ObjectUtils.isEmpty(getPackagesToScan());
|
||||
|
||||
if (hasContextPath && (hasClassesToBeBound || hasPackagesToScan) ||
|
||||
(hasClassesToBeBound && hasPackagesToScan)) {
|
||||
throw new IllegalArgumentException("Specify either 'contextPath', 'classesToBeBound', " +
|
||||
"or 'packagesToScan'");
|
||||
}
|
||||
if (!hasContextPath && !hasClassesToBeBound && !hasPackagesToScan) {
|
||||
throw new IllegalArgumentException(
|
||||
"Setting either 'contextPath', 'classesToBeBound', " + "or 'packagesToScan' is required");
|
||||
}
|
||||
if (!this.lazyInit) {
|
||||
getJaxbContext();
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.schemaResources)) {
|
||||
this.schema = loadSchema(this.schemaResources, this.schemaLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized JAXBContext getJaxbContext() {
|
||||
if (this.jaxbContext == null) {
|
||||
try {
|
||||
if (StringUtils.hasLength(getContextPath())) {
|
||||
this.jaxbContext = createJaxbContextFromContextPath();
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(getClassesToBeBound())) {
|
||||
this.jaxbContext = createJaxbContextFromClasses();
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(getPackagesToScan())) {
|
||||
this.jaxbContext = createJaxbContextFromPackages();
|
||||
}
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw convertJaxbException(ex);
|
||||
}
|
||||
}
|
||||
return jaxbContext;
|
||||
}
|
||||
|
||||
private JAXBContext createJaxbContextFromContextPath() throws JAXBException {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Creating JAXBContext with context path [" + getContextPath() + "]");
|
||||
}
|
||||
if (this.jaxbContextProperties != null) {
|
||||
if (this.beanClassLoader != null) {
|
||||
return JAXBContext.newInstance(getContextPath(), this.beanClassLoader, this.jaxbContextProperties);
|
||||
}
|
||||
else {
|
||||
return JAXBContext.newInstance(getContextPath(), ClassUtils.getDefaultClassLoader(), this.jaxbContextProperties);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.beanClassLoader != null) {
|
||||
return JAXBContext.newInstance(getContextPath(), this.beanClassLoader);
|
||||
}
|
||||
else {
|
||||
return JAXBContext.newInstance(getContextPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JAXBContext createJaxbContextFromClasses() throws JAXBException {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Creating JAXBContext with classes to be bound [" +
|
||||
StringUtils.arrayToCommaDelimitedString(getClassesToBeBound()) + "]");
|
||||
}
|
||||
if (this.jaxbContextProperties != null) {
|
||||
return JAXBContext.newInstance(getClassesToBeBound(), this.jaxbContextProperties);
|
||||
}
|
||||
else {
|
||||
return JAXBContext.newInstance(getClassesToBeBound());
|
||||
}
|
||||
}
|
||||
|
||||
private JAXBContext createJaxbContextFromPackages() throws JAXBException {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Creating JAXBContext by scanning packages [" +
|
||||
StringUtils.arrayToCommaDelimitedString(getPackagesToScan()) + "]");
|
||||
}
|
||||
ClassPathJaxb2TypeScanner scanner = new ClassPathJaxb2TypeScanner(getPackagesToScan());
|
||||
scanner.setResourceLoader(this.resourceLoader);
|
||||
scanner.scanPackages();
|
||||
Class<?>[] jaxb2Classes = scanner.getJaxb2Classes();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found JAXB2 classes: [" + StringUtils.arrayToCommaDelimitedString(jaxb2Classes) + "]");
|
||||
}
|
||||
if (this.jaxbContextProperties != null) {
|
||||
return JAXBContext.newInstance(jaxb2Classes, this.jaxbContextProperties);
|
||||
}
|
||||
else {
|
||||
return JAXBContext.newInstance(jaxb2Classes);
|
||||
}
|
||||
}
|
||||
|
||||
private Schema loadSchema(Resource[] resources, String schemaLanguage) throws IOException, SAXException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Setting validation schema to " + StringUtils.arrayToCommaDelimitedString(this.schemaResources));
|
||||
}
|
||||
Assert.notEmpty(resources, "No resources given");
|
||||
Assert.hasLength(schemaLanguage, "No schema language provided");
|
||||
Source[] schemaSources = new Source[resources.length];
|
||||
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
|
||||
for (int i = 0; i < resources.length; i++) {
|
||||
Assert.notNull(resources[i], "Resource is null");
|
||||
Assert.isTrue(resources[i].exists(), "Resource " + resources[i] + " does not exist");
|
||||
InputSource inputSource = SaxResourceUtils.createInputSource(resources[i]);
|
||||
schemaSources[i] = new SAXSource(xmlReader, inputSource);
|
||||
}
|
||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
|
||||
if (schemaResourceResolver != null) {
|
||||
schemaFactory.setResourceResolver(schemaResourceResolver);
|
||||
}
|
||||
return schemaFactory.newSchema(schemaSources);
|
||||
}
|
||||
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
if (supportJaxbElementClass && JAXBElement.class.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
}
|
||||
return supportsInternal(clazz, true);
|
||||
}
|
||||
|
||||
public boolean supports(Type genericType) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericType;
|
||||
if (JAXBElement.class.equals(parameterizedType.getRawType()) &&
|
||||
parameterizedType.getActualTypeArguments().length == 1) {
|
||||
Type typeArgument = parameterizedType.getActualTypeArguments()[0];
|
||||
if (typeArgument instanceof Class) {
|
||||
Class<?> classArgument = (Class<?>) typeArgument;
|
||||
return (isPrimitiveWrapper(classArgument) || isStandardClass(classArgument) ||
|
||||
supportsInternal(classArgument, false));
|
||||
}
|
||||
else if (typeArgument instanceof GenericArrayType) {
|
||||
GenericArrayType arrayType = (GenericArrayType) typeArgument;
|
||||
return arrayType.getGenericComponentType().equals(Byte.TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (genericType instanceof Class) {
|
||||
Class<?> clazz = (Class<?>) genericType;
|
||||
return supportsInternal(clazz, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement) {
|
||||
if (checkForXmlRootElement && AnnotationUtils.findAnnotation(clazz, XmlRootElement.class) == null) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.hasLength(getContextPath())) {
|
||||
String packageName = ClassUtils.getPackageName(clazz);
|
||||
String[] contextPaths = StringUtils.tokenizeToStringArray(getContextPath(), ":");
|
||||
for (String contextPath : contextPaths) {
|
||||
if (contextPath.equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(getClassesToBeBound())) {
|
||||
return Arrays.asList(getClassesToBeBound()).contains(clazz);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given type is a primitive wrapper type.
|
||||
* Compare section 8.5.1 of the JAXB2 spec.
|
||||
*/
|
||||
private boolean isPrimitiveWrapper(Class<?> clazz) {
|
||||
return Boolean.class.equals(clazz) ||
|
||||
Byte.class.equals(clazz) ||
|
||||
Short.class.equals(clazz) ||
|
||||
Integer.class.equals(clazz) ||
|
||||
Long.class.equals(clazz) ||
|
||||
Float.class.equals(clazz) ||
|
||||
Double.class.equals(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given type is a standard class.
|
||||
* Compare section 8.5.2 of the JAXB2 spec.
|
||||
*/
|
||||
private boolean isStandardClass(Class<?> clazz) {
|
||||
return String.class.equals(clazz) ||
|
||||
BigInteger.class.isAssignableFrom(clazz) ||
|
||||
BigDecimal.class.isAssignableFrom(clazz) ||
|
||||
Calendar.class.isAssignableFrom(clazz) ||
|
||||
Date.class.isAssignableFrom(clazz) ||
|
||||
QName.class.isAssignableFrom(clazz) ||
|
||||
URI.class.equals(clazz) ||
|
||||
XMLGregorianCalendar.class.isAssignableFrom(clazz) ||
|
||||
Duration.class.isAssignableFrom(clazz) ||
|
||||
Image.class.equals(clazz) ||
|
||||
DataHandler.class.equals(clazz) ||
|
||||
// Source and subclasses should be supported according to the JAXB2 spec, but aren't in the RI
|
||||
// Source.class.isAssignableFrom(clazz) ||
|
||||
UUID.class.equals(clazz);
|
||||
|
||||
}
|
||||
|
||||
// Marshalling
|
||||
|
||||
public void marshal(Object graph, Result result) throws XmlMappingException {
|
||||
marshal(graph, result, null);
|
||||
}
|
||||
|
||||
public void marshal(Object graph, Result result, MimeContainer mimeContainer) throws XmlMappingException {
|
||||
try {
|
||||
Marshaller marshaller = createMarshaller();
|
||||
if (this.mtomEnabled && mimeContainer != null) {
|
||||
marshaller.setAttachmentMarshaller(new Jaxb2AttachmentMarshaller(mimeContainer));
|
||||
}
|
||||
if (StaxUtils.isStaxResult(result)) {
|
||||
marshalStaxResult(marshaller, graph, result);
|
||||
}
|
||||
else {
|
||||
marshaller.marshal(graph, result);
|
||||
}
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw convertJaxbException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void marshalStaxResult(Marshaller jaxbMarshaller, Object graph, Result staxResult) throws JAXBException {
|
||||
XMLStreamWriter streamWriter = StaxUtils.getXMLStreamWriter(staxResult);
|
||||
if (streamWriter != null) {
|
||||
jaxbMarshaller.marshal(graph, streamWriter);
|
||||
}
|
||||
else {
|
||||
XMLEventWriter eventWriter = StaxUtils.getXMLEventWriter(staxResult);
|
||||
if (eventWriter != null) {
|
||||
jaxbMarshaller.marshal(graph, eventWriter);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StAX Result contains neither XMLStreamWriter nor XMLEventConsumer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a newly created JAXB marshaller. JAXB marshallers are not necessarily thread safe.
|
||||
*/
|
||||
protected Marshaller createMarshaller() {
|
||||
try {
|
||||
Marshaller marshaller = getJaxbContext().createMarshaller();
|
||||
initJaxbMarshaller(marshaller);
|
||||
return marshaller;
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw convertJaxbException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that can be overridden by concrete JAXB marshallers for custom initialization behavior.
|
||||
* Gets called after creation of JAXB <code>Marshaller</code>, and after the respective properties have been set.
|
||||
* <p>The default implementation sets the {@link #setMarshallerProperties(Map) defined properties}, the {@link
|
||||
* #setValidationEventHandler(ValidationEventHandler) validation event handler}, the {@link #setSchemas(Resource[])
|
||||
* schemas}, {@link #setMarshallerListener(javax.xml.bind.Marshaller.Listener) listener}, and
|
||||
* {@link #setAdapters(XmlAdapter[]) adapters}.
|
||||
*/
|
||||
protected void initJaxbMarshaller(Marshaller marshaller) throws JAXBException {
|
||||
if (this.marshallerProperties != null) {
|
||||
for (String name : this.marshallerProperties.keySet()) {
|
||||
marshaller.setProperty(name, this.marshallerProperties.get(name));
|
||||
}
|
||||
}
|
||||
if (this.marshallerListener != null) {
|
||||
marshaller.setListener(this.marshallerListener);
|
||||
}
|
||||
if (this.validationEventHandler != null) {
|
||||
marshaller.setEventHandler(this.validationEventHandler);
|
||||
}
|
||||
if (this.adapters != null) {
|
||||
for (XmlAdapter<?, ?> adapter : this.adapters) {
|
||||
marshaller.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
if (this.schema != null) {
|
||||
marshaller.setSchema(this.schema);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
public Object unmarshal(Source source) throws XmlMappingException {
|
||||
return unmarshal(source, null);
|
||||
}
|
||||
|
||||
public Object unmarshal(Source source, MimeContainer mimeContainer) throws XmlMappingException {
|
||||
try {
|
||||
Unmarshaller unmarshaller = createUnmarshaller();
|
||||
if (this.mtomEnabled && mimeContainer != null) {
|
||||
unmarshaller.setAttachmentUnmarshaller(new Jaxb2AttachmentUnmarshaller(mimeContainer));
|
||||
}
|
||||
if (StaxUtils.isStaxSource(source)) {
|
||||
return unmarshalStaxSource(unmarshaller, source);
|
||||
}
|
||||
else {
|
||||
return unmarshaller.unmarshal(source);
|
||||
}
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw convertJaxbException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object unmarshalStaxSource(Unmarshaller jaxbUnmarshaller, Source staxSource) throws JAXBException {
|
||||
XMLStreamReader streamReader = StaxUtils.getXMLStreamReader(staxSource);
|
||||
if (streamReader != null) {
|
||||
return jaxbUnmarshaller.unmarshal(streamReader);
|
||||
}
|
||||
else {
|
||||
XMLEventReader eventReader = StaxUtils.getXMLEventReader(staxSource);
|
||||
if (eventReader != null) {
|
||||
return jaxbUnmarshaller.unmarshal(eventReader);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StaxSource contains neither XMLStreamReader nor XMLEventReader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a newly created JAXB unmarshaller. JAXB unmarshallers are not necessarily thread safe.
|
||||
*/
|
||||
protected Unmarshaller createUnmarshaller() {
|
||||
try {
|
||||
Unmarshaller unmarshaller = getJaxbContext().createUnmarshaller();
|
||||
initJaxbUnmarshaller(unmarshaller);
|
||||
return unmarshaller;
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw convertJaxbException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that can be overridden by concrete JAXB marshallers for custom initialization behavior.
|
||||
* Gets called after creation of JAXB <code>Marshaller</code>, and after the respective properties have been set.
|
||||
* <p>The default implementation sets the {@link #setUnmarshallerProperties(Map) defined properties}, the {@link
|
||||
* #setValidationEventHandler(ValidationEventHandler) validation event handler}, the {@link #setSchemas(Resource[])
|
||||
* schemas}, {@link #setUnmarshallerListener(javax.xml.bind.Unmarshaller.Listener) listener}, and
|
||||
* {@link #setAdapters(XmlAdapter[]) adapters}.
|
||||
*/
|
||||
protected void initJaxbUnmarshaller(Unmarshaller unmarshaller) throws JAXBException {
|
||||
if (this.unmarshallerProperties != null) {
|
||||
for (String name : this.unmarshallerProperties.keySet()) {
|
||||
unmarshaller.setProperty(name, this.unmarshallerProperties.get(name));
|
||||
}
|
||||
}
|
||||
if (this.unmarshallerListener != null) {
|
||||
unmarshaller.setListener(this.unmarshallerListener);
|
||||
}
|
||||
if (this.validationEventHandler != null) {
|
||||
unmarshaller.setEventHandler(this.validationEventHandler);
|
||||
}
|
||||
if (this.adapters != null) {
|
||||
for (XmlAdapter<?, ?> adapter : this.adapters) {
|
||||
unmarshaller.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
if (this.schema != null) {
|
||||
unmarshaller.setSchema(this.schema);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given <code>JAXBException</code> to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> hierarchy.
|
||||
* @param ex <code>JAXBException</code> that occured
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
protected XmlMappingException convertJaxbException(JAXBException ex) {
|
||||
if (ex instanceof ValidationException) {
|
||||
return new ValidationFailureException("JAXB validation exception", ex);
|
||||
}
|
||||
else if (ex instanceof MarshalException) {
|
||||
return new MarshallingFailureException("JAXB marshalling exception", ex);
|
||||
}
|
||||
else if (ex instanceof UnmarshalException) {
|
||||
return new UnmarshallingFailureException("JAXB unmarshalling exception", ex);
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
return new UncategorizedMappingException("Unknown JAXB exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Jaxb2AttachmentMarshaller extends AttachmentMarshaller {
|
||||
|
||||
private final MimeContainer mimeContainer;
|
||||
|
||||
private Jaxb2AttachmentMarshaller(MimeContainer mimeContainer) {
|
||||
this.mimeContainer = mimeContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addMtomAttachment(byte[] data, int offset, int length, String mimeType,
|
||||
String elementNamespace, String elementLocalName) {
|
||||
ByteArrayDataSource dataSource = new ByteArrayDataSource(mimeType, data, offset, length);
|
||||
return addMtomAttachment(new DataHandler(dataSource), elementNamespace, elementLocalName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addMtomAttachment(DataHandler dataHandler, String elementNamespace, String elementLocalName) {
|
||||
String host = getHost(elementNamespace, dataHandler);
|
||||
String contentId = UUID.randomUUID() + "@" + host;
|
||||
this.mimeContainer.addAttachment("<" + contentId + ">", dataHandler);
|
||||
try {
|
||||
contentId = URLEncoder.encode(contentId, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
// ignore
|
||||
}
|
||||
return CID + contentId;
|
||||
}
|
||||
|
||||
private String getHost(String elementNamespace, DataHandler dataHandler) {
|
||||
try {
|
||||
URI uri = new URI(elementNamespace);
|
||||
return uri.getHost();
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
// ignore
|
||||
}
|
||||
return dataHandler.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addSwaRefAttachment(DataHandler dataHandler) {
|
||||
String contentId = UUID.randomUUID() + "@" + dataHandler.getName();
|
||||
mimeContainer.addAttachment(contentId, dataHandler);
|
||||
return contentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isXOPPackage() {
|
||||
return this.mimeContainer.convertToXopPackage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Jaxb2AttachmentUnmarshaller extends AttachmentUnmarshaller {
|
||||
|
||||
private final MimeContainer mimeContainer;
|
||||
|
||||
private Jaxb2AttachmentUnmarshaller(MimeContainer mimeContainer) {
|
||||
this.mimeContainer = mimeContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getAttachmentAsByteArray(String cid) {
|
||||
try {
|
||||
DataHandler dataHandler = getAttachmentAsDataHandler(cid);
|
||||
return FileCopyUtils.copyToByteArray(dataHandler.getInputStream());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UnmarshallingFailureException("Couldn't read attachment", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataHandler getAttachmentAsDataHandler(String contentId) {
|
||||
if (contentId.startsWith(CID)) {
|
||||
contentId = contentId.substring(CID.length());
|
||||
try {
|
||||
contentId = URLDecoder.decode(contentId, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
// ignore
|
||||
}
|
||||
contentId = '<' + contentId + '>';
|
||||
}
|
||||
return this.mimeContainer.getAttachment(contentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isXOPPackage() {
|
||||
return this.mimeContainer.isXopPackage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DataSource that wraps around a byte array.
|
||||
*/
|
||||
private static class ByteArrayDataSource implements DataSource {
|
||||
|
||||
private byte[] data;
|
||||
|
||||
private String contentType;
|
||||
|
||||
private int offset;
|
||||
|
||||
private int length;
|
||||
|
||||
private ByteArrayDataSource(String contentType, byte[] data, int offset, int length) {
|
||||
this.contentType = contentType;
|
||||
this.data = data;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(this.data, this.offset, this.length);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "ByteArrayDataSource";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package providing integration of <a href="http://java.sun.com/webservices/jaxb/">JAXB</a> with Springs O/X Mapping
|
||||
* support
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.jaxb;
|
||||
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.jibx;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.jibx.runtime.BindingDirectory;
|
||||
import org.jibx.runtime.IBindingFactory;
|
||||
import org.jibx.runtime.IMarshallingContext;
|
||||
import org.jibx.runtime.IUnmarshallingContext;
|
||||
import org.jibx.runtime.IXMLReader;
|
||||
import org.jibx.runtime.IXMLWriter;
|
||||
import org.jibx.runtime.JiBXException;
|
||||
import org.jibx.runtime.ValidationException;
|
||||
import org.jibx.runtime.impl.MarshallingContext;
|
||||
import org.jibx.runtime.impl.StAXReaderWrapper;
|
||||
import org.jibx.runtime.impl.StAXWriter;
|
||||
import org.jibx.runtime.impl.UnmarshallingContext;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.oxm.MarshallingFailureException;
|
||||
import org.springframework.oxm.UnmarshallingFailureException;
|
||||
import org.springframework.oxm.ValidationFailureException;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.oxm.support.AbstractMarshaller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>Marshaller</code> and <code>Unmarshaller</code> interfaces for JiBX.
|
||||
*
|
||||
* <p>The typical usage will be to set the <code>targetClass</code> and optionally the
|
||||
* <code>bindingName</code> property on this bean.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see org.jibx.runtime.IMarshallingContext
|
||||
* @see org.jibx.runtime.IUnmarshallingContext
|
||||
*/
|
||||
public class JibxMarshaller extends AbstractMarshaller implements InitializingBean {
|
||||
|
||||
private static final String DEFAULT_BINDING_NAME = "binding";
|
||||
|
||||
private Class<?> targetClass;
|
||||
|
||||
private String targetPackage;
|
||||
|
||||
private String bindingName;
|
||||
|
||||
private int indent = -1;
|
||||
|
||||
private String encoding = "UTF-8";
|
||||
|
||||
private Boolean standalone;
|
||||
|
||||
private String docTypeRootElementName;
|
||||
|
||||
private String docTypeSystemId;
|
||||
|
||||
private String docTypePublicId;
|
||||
|
||||
private String docTypeInternalSubset;
|
||||
|
||||
private IBindingFactory bindingFactory;
|
||||
|
||||
private TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
|
||||
|
||||
/**
|
||||
* Set the target class for this instance. Setting either this property or the
|
||||
* {@link #setTargetPackage(String) targetPackage} property is required.
|
||||
*
|
||||
* <p>If this property is set, {@link #setTargetPackage(String) targetPackage} is ignored.
|
||||
*/
|
||||
public void setTargetClass(Class<?> targetClass) {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target package for this instance. Setting either this property or the
|
||||
* {@link #setTargetClass(Class) targetClass} property is required.
|
||||
*
|
||||
* <p>If {@link #setTargetClass(Class) targetClass} is set, this property is ignored.
|
||||
*/
|
||||
public void setTargetPackage(String targetPackage) {
|
||||
this.targetPackage = targetPackage;
|
||||
}
|
||||
/**
|
||||
* Set the optional binding name for this instance.
|
||||
*/
|
||||
public void setBindingName(String bindingName) {
|
||||
this.bindingName = bindingName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of nesting indent spaces. Default is <code>-1</code>, i.e. no indentation.
|
||||
*/
|
||||
public void setIndent(int indent) {
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the document encoding using for marshalling. Default is UTF-8.
|
||||
*/
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the document standalone flag for marshalling. By default, this flag is not present.
|
||||
*/
|
||||
public void setStandalone(Boolean standalone) {
|
||||
this.standalone = standalone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root element name for the DTD declaration written when marshalling. By default, this is
|
||||
* {@code null} (i.e. no DTD declaration is written). If set to a value, the system ID or public ID also need to
|
||||
* be set.
|
||||
*
|
||||
* @see #setDocTypeSystemId(String)
|
||||
* @see #setDocTypePublicId(String)
|
||||
*/
|
||||
public void setDocTypeRootElementName(String docTypeRootElementName) {
|
||||
this.docTypeRootElementName = docTypeRootElementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system Id for the DTD declaration written when marshalling. By default, this is
|
||||
* {@code null}. Only used when the root element also has been set. Set either this property or
|
||||
* {@code docTypePublicId}, not both.
|
||||
*
|
||||
* @see #setDocTypeRootElementName(String)
|
||||
*/
|
||||
public void setDocTypeSystemId(String docTypeSystemId) {
|
||||
this.docTypeSystemId = docTypeSystemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the public Id for the DTD declaration written when marshalling. By default, this is
|
||||
* {@code null}. Only used when the root element also has been set. Set either this property or
|
||||
* {@code docTypeSystemId}, not both.
|
||||
*
|
||||
* @see #setDocTypeRootElementName(String)
|
||||
*/
|
||||
public void setDocTypePublicId(String docTypePublicId) {
|
||||
this.docTypePublicId = docTypePublicId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal subset Id for the DTD declaration written when marshalling. By default, this is
|
||||
* {@code null}. Only used when the root element also has been set.
|
||||
*
|
||||
* @see #setDocTypeRootElementName(String)
|
||||
*/
|
||||
public void setDocTypeInternalSubset(String docTypeInternalSubset) {
|
||||
this.docTypeInternalSubset = docTypeInternalSubset;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws JiBXException {
|
||||
if (this.targetClass != null) {
|
||||
if (StringUtils.hasLength(this.bindingName)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Configured for target class [" + this.targetClass + "] using binding [" + this.bindingName + "]");
|
||||
}
|
||||
this.bindingFactory = BindingDirectory.getFactory(this.bindingName, this.targetClass);
|
||||
}
|
||||
else {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Configured for target class [" + this.targetClass + "]");
|
||||
}
|
||||
this.bindingFactory = BindingDirectory.getFactory(this.targetClass);
|
||||
}
|
||||
} else if (this.targetPackage != null) {
|
||||
if (!StringUtils.hasLength(bindingName)) {
|
||||
bindingName = DEFAULT_BINDING_NAME;
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Configured for target package [" + targetPackage + "] using binding [" + bindingName + "]");
|
||||
}
|
||||
this.bindingFactory = BindingDirectory.getFactory(bindingName, targetPackage);
|
||||
} else {
|
||||
throw new IllegalArgumentException("either 'targetClass' or 'targetPackage' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
Assert.notNull(clazz, "'clazz' must not be null");
|
||||
if (this.targetClass != null) {
|
||||
return this.targetClass.equals(clazz);
|
||||
}
|
||||
String[] mappedClasses = this.bindingFactory.getMappedClasses();
|
||||
String className = clazz.getName();
|
||||
for (String mappedClass : mappedClasses) {
|
||||
if (className.equals(mappedClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Supported Marshalling
|
||||
|
||||
@Override
|
||||
protected void marshalOutputStream(Object graph, OutputStream outputStream)
|
||||
throws XmlMappingException, IOException {
|
||||
try {
|
||||
IMarshallingContext marshallingContext = createMarshallingContext();
|
||||
marshallingContext.startDocument(this.encoding, this.standalone, outputStream);
|
||||
marshalDocument(marshallingContext, graph);
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
|
||||
try {
|
||||
IMarshallingContext marshallingContext = createMarshallingContext();
|
||||
marshallingContext.startDocument(this.encoding, this.standalone, writer);
|
||||
marshalDocument(marshallingContext, graph);
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void marshalDocument(IMarshallingContext marshallingContext, Object graph) throws IOException,
|
||||
JiBXException {
|
||||
if (StringUtils.hasLength(docTypeRootElementName)) {
|
||||
IXMLWriter xmlWriter = marshallingContext.getXmlWriter();
|
||||
xmlWriter.writeDocType(docTypeRootElementName, docTypeSystemId, docTypePublicId, docTypeInternalSubset);
|
||||
}
|
||||
marshallingContext.marshalDocument(graph);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
|
||||
try {
|
||||
MarshallingContext marshallingContext = (MarshallingContext) createMarshallingContext();
|
||||
IXMLWriter xmlWriter = new StAXWriter(marshallingContext.getNamespaces(), streamWriter);
|
||||
marshallingContext.setXmlWriter(xmlWriter);
|
||||
marshallingContext.marshalDocument(graph);
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Unsupported Marshalling
|
||||
|
||||
@Override
|
||||
protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
|
||||
try {
|
||||
// JiBX does not support DOM natively, so we write to a buffer first, and transform that to the Node
|
||||
Result result = new DOMResult(node);
|
||||
transformAndMarshal(graph, result);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MarshallingFailureException("JiBX marshalling exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
|
||||
throws XmlMappingException {
|
||||
try {
|
||||
// JiBX does not support SAX natively, so we write to a buffer first, and transform that to the handlers
|
||||
SAXResult saxResult = new SAXResult(contentHandler);
|
||||
saxResult.setLexicalHandler(lexicalHandler);
|
||||
transformAndMarshal(graph, saxResult);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MarshallingFailureException("JiBX marshalling exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void transformAndMarshal(Object graph, Result result) throws IOException {
|
||||
try {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
marshalOutputStream(graph, os);
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
Transformer transformer = this.transformerFactory.newTransformer();
|
||||
transformer.transform(new StreamSource(is), result);
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
throw new MarshallingFailureException(
|
||||
"Could not transform to [" + ClassUtils.getShortName(result.getClass()) + "]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) {
|
||||
ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter);
|
||||
marshalSaxHandlers(graph, contentHandler, null);
|
||||
}
|
||||
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
@Override
|
||||
protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
|
||||
try {
|
||||
IUnmarshallingContext unmarshallingContext = createUnmarshallingContext();
|
||||
return unmarshallingContext.unmarshalDocument(inputStream, null);
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
|
||||
try {
|
||||
IUnmarshallingContext unmarshallingContext = createUnmarshallingContext();
|
||||
return unmarshallingContext.unmarshalDocument(reader);
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalXmlStreamReader(XMLStreamReader streamReader) {
|
||||
try {
|
||||
UnmarshallingContext unmarshallingContext = (UnmarshallingContext) createUnmarshallingContext();
|
||||
IXMLReader xmlReader = new StAXReaderWrapper(streamReader, null, true);
|
||||
unmarshallingContext.setDocument(xmlReader);
|
||||
return unmarshallingContext.unmarshalElement();
|
||||
}
|
||||
catch (JiBXException ex) {
|
||||
throw convertJibxException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalXmlEventReader(XMLEventReader eventReader) {
|
||||
try {
|
||||
XMLStreamReader streamReader = StaxUtils.createEventStreamReader(eventReader);
|
||||
return unmarshalXmlStreamReader(streamReader);
|
||||
}
|
||||
catch (XMLStreamException ex) {
|
||||
return new UnmarshallingFailureException("JiBX unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unsupported Unmarshalling
|
||||
|
||||
@Override
|
||||
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
|
||||
try {
|
||||
return transformAndUnmarshal(new DOMSource(node));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UnmarshallingFailureException("JiBX unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
|
||||
throws XmlMappingException, IOException {
|
||||
return transformAndUnmarshal(new SAXSource(xmlReader, inputSource));
|
||||
}
|
||||
|
||||
private Object transformAndUnmarshal(Source source) throws IOException {
|
||||
try {
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
transformer.transform(source, new StreamResult(os));
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
return unmarshalInputStream(is);
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
throw new MarshallingFailureException(
|
||||
"Could not transform from [" + ClassUtils.getShortName(source.getClass()) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new <code>IMarshallingContext</code>, configured with the correct indentation.
|
||||
* @return the created marshalling context
|
||||
* @throws JiBXException in case of errors
|
||||
*/
|
||||
protected IMarshallingContext createMarshallingContext() throws JiBXException {
|
||||
IMarshallingContext marshallingContext = this.bindingFactory.createMarshallingContext();
|
||||
marshallingContext.setIndent(this.indent);
|
||||
return marshallingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>IUnmarshallingContext</code>.
|
||||
* @return the created unmarshalling context
|
||||
* @throws JiBXException in case of errors
|
||||
*/
|
||||
protected IUnmarshallingContext createUnmarshallingContext() throws JiBXException {
|
||||
return this.bindingFactory.createUnmarshallingContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given <code>JiBXException</code> to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> hierarchy.
|
||||
* <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
|
||||
* unmarshalling, since JiBX itself does not make this distinction in its exception hierarchy.
|
||||
* @param ex <code>JiBXException</code> that occured
|
||||
* @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
|
||||
* or unmarshalling (<code>false</code>)
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
public XmlMappingException convertJibxException(JiBXException ex, boolean marshalling) {
|
||||
if (ex instanceof ValidationException) {
|
||||
return new ValidationFailureException("JiBX validation exception", ex);
|
||||
}
|
||||
else {
|
||||
if (marshalling) {
|
||||
return new MarshallingFailureException("JiBX marshalling exception", ex);
|
||||
}
|
||||
else {
|
||||
return new UnmarshallingFailureException("JiBX unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package providing integration of <a href="http://jibx.sourceforge.net/">JiBX</a> with Springs O/X Mapping
|
||||
* support
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.jibx;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.mime;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
|
||||
/**
|
||||
* Represents a container for MIME attachments
|
||||
* Concrete implementations might adapt a SOAPMessage or an email message.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/">XML-binary Optimized Packaging</a>
|
||||
*/
|
||||
public interface MimeContainer {
|
||||
|
||||
/**
|
||||
* Indicate whether this container is a XOP package.
|
||||
* @return <code>true</code> when the constraints specified in
|
||||
* <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/#identifying_xop_documents">Identifying XOP Documents</a>
|
||||
* are met
|
||||
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/#xop_packages">XOP Packages</a>
|
||||
*/
|
||||
boolean isXopPackage();
|
||||
|
||||
/**
|
||||
* Turn this message into a XOP package.
|
||||
* @return <code>true</code> when the message actually is a XOP package
|
||||
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/#xop_packages">XOP Packages</a>
|
||||
*/
|
||||
boolean convertToXopPackage();
|
||||
|
||||
/**
|
||||
* Add the given data handler as an attachment to this container.
|
||||
* @param contentId the content id of the attachment
|
||||
* @param dataHandler the data handler containing the data of the attachment
|
||||
*/
|
||||
void addAttachment(String contentId, DataHandler dataHandler);
|
||||
|
||||
/**
|
||||
* Return the attachment with the given content id, or <code>null</code> if not found.
|
||||
* @param contentId the content id
|
||||
* @return the attachment, as a data handler
|
||||
*/
|
||||
DataHandler getAttachment(String contentId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.mime;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Result;
|
||||
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link Marshaller} that can use MIME attachments to optimize
|
||||
* storage of binary data. Attachments can be added as MTOM, XOP, or SwA.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see <a href="http://www.w3.org/TR/2004/WD-soap12-mtom-20040608/">SOAP Message Transmission Optimization Mechanism</a>
|
||||
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/">XML-binary Optimized Packaging</a>
|
||||
*/
|
||||
public interface MimeMarshaller extends Marshaller {
|
||||
|
||||
/**
|
||||
* Marshals the object graph with the given root into the provided {@link Result},
|
||||
* writing binary data to a {@link MimeContainer}.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param result the result to marshal to
|
||||
* @param mimeContainer the MIME container to write extracted binary content to
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
void marshal(Object graph, Result result, MimeContainer mimeContainer) throws XmlMappingException, IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.mime;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link org.springframework.oxm.Unmarshaller} that can use MIME attachments
|
||||
* to optimize storage of binary data. Attachments can be added as MTOM, XOP, or SwA.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see <a href="http://www.w3.org/TR/2004/WD-soap12-mtom-20040608/">SOAP Message Transmission Optimization Mechanism</a>
|
||||
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/">XML-binary Optimized Packaging</a>
|
||||
*/
|
||||
public interface MimeUnmarshaller extends Unmarshaller {
|
||||
|
||||
/**
|
||||
* Unmarshals the given provided {@link Source} into an object graph,
|
||||
* reading binary attachments from a {@link MimeContainer}.
|
||||
* @param source the source to marshal from
|
||||
* @param mimeContainer the MIME container to read extracted binary content from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
* @throws IOException if an I/O Exception occurs
|
||||
*/
|
||||
Object unmarshal(Source source, MimeContainer mimeContainer) throws XmlMappingException, IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Contains (un)marshallers optimized to store binary data in MIME attachments.
|
||||
* </htm
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.mime;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Root package for Spring's O/X Mapping integration classes. Contains generic Marshaller and Unmarshaller interfaces,
|
||||
* and XmlMappingExceptions related to O/X Mapping
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm;
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.stax.StAXSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.UnmarshallingFailureException;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the <code>Marshaller</code> and <code>Unmarshaller</code> interface.
|
||||
* This implementation inspects the given <code>Source</code> or <code>Result</code>, and defers
|
||||
* further handling to overridable template methods.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private DocumentBuilderFactory documentBuilderFactory;
|
||||
|
||||
private final Object documentBuilderFactoryMonitor = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Marshals the object graph with the given root into the provided <code>javax.xml.transform.Result</code>.
|
||||
* <p>This implementation inspects the given result, and calls <code>marshalDomResult</code>,
|
||||
* <code>marshalSaxResult</code>, or <code>marshalStreamResult</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param result the result to marshal to
|
||||
* @throws IOException if an I/O exception occurs
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @throws IllegalArgumentException if <code>result</code> if neither a <code>DOMResult</code>,
|
||||
* a <code>SAXResult</code>, nor a <code>StreamResult</code>
|
||||
* @see #marshalDomResult(Object, javax.xml.transform.dom.DOMResult)
|
||||
* @see #marshalSaxResult(Object, javax.xml.transform.sax.SAXResult)
|
||||
* @see #marshalStreamResult(Object, javax.xml.transform.stream.StreamResult)
|
||||
*/
|
||||
public final void marshal(Object graph, Result result) throws IOException, XmlMappingException {
|
||||
if (result instanceof DOMResult) {
|
||||
marshalDomResult(graph, (DOMResult) result);
|
||||
}
|
||||
else if (StaxUtils.isStaxResult(result)) {
|
||||
marshalStaxResult(graph, result);
|
||||
}
|
||||
else if (result instanceof SAXResult) {
|
||||
marshalSaxResult(graph, (SAXResult) result);
|
||||
}
|
||||
else if (result instanceof StreamResult) {
|
||||
marshalStreamResult(graph, (StreamResult) result);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown Result type: " + result.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshals the given provided <code>javax.xml.transform.Source</code> into an object graph.
|
||||
* <p>This implementation inspects the given result, and calls <code>unmarshalDomSource</code>,
|
||||
* <code>unmarshalSaxSource</code>, or <code>unmarshalStreamSource</code>.
|
||||
* @param source the source to marshal from
|
||||
* @return the object graph
|
||||
* @throws IOException if an I/O Exception occurs
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
* @throws IllegalArgumentException if <code>source</code> is neither a <code>DOMSource</code>,
|
||||
* a <code>SAXSource</code>, nor a <code>StreamSource</code>
|
||||
* @see #unmarshalDomSource(javax.xml.transform.dom.DOMSource)
|
||||
* @see #unmarshalSaxSource(javax.xml.transform.sax.SAXSource)
|
||||
* @see #unmarshalStreamSource(javax.xml.transform.stream.StreamSource)
|
||||
*/
|
||||
public final Object unmarshal(Source source) throws IOException, XmlMappingException {
|
||||
if (source instanceof DOMSource) {
|
||||
return unmarshalDomSource((DOMSource) source);
|
||||
}
|
||||
else if (StaxUtils.isStaxSource(source)) {
|
||||
return unmarshalStaxSource(source);
|
||||
}
|
||||
else if (source instanceof SAXSource) {
|
||||
return unmarshalSaxSource((SAXSource) source);
|
||||
}
|
||||
else if (source instanceof StreamSource) {
|
||||
return unmarshalStreamSource((StreamSource) source);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown Source type: " + source.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>DocumentBuilder</code> that this marshaller will use for creating
|
||||
* DOM documents when passed an empty <code>DOMSource</code>.
|
||||
* <p>Can be overridden in subclasses, adding further initialization of the builder.
|
||||
* @param factory the <code>DocumentBuilderFactory</code> that the DocumentBuilder should be created with
|
||||
* @return the <code>DocumentBuilder</code>
|
||||
* @throws ParserConfigurationException if thrown by JAXP methods
|
||||
*/
|
||||
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
|
||||
throws ParserConfigurationException {
|
||||
|
||||
return factory.newDocumentBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>DocumentBuilder</code> that this marshaller will use for creating
|
||||
* DOM documents when passed an empty <code>DOMSource</code>.
|
||||
* <p>The resulting <code>DocumentBuilderFactory</code> is cached, so this method
|
||||
* will only be called once.
|
||||
* @return the DocumentBuilderFactory
|
||||
* @throws ParserConfigurationException if thrown by JAXP methods
|
||||
*/
|
||||
protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserConfigurationException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setNamespaceAware(true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>XMLReader</code> that this marshaller will when passed an empty <code>SAXSource</code>.
|
||||
* @return the XMLReader
|
||||
* @throws SAXException if thrown by JAXP methods
|
||||
*/
|
||||
protected XMLReader createXmlReader() throws SAXException {
|
||||
return XMLReaderFactory.createXMLReader();
|
||||
}
|
||||
|
||||
|
||||
// Marshalling
|
||||
|
||||
/**
|
||||
* Template method for handling <code>DOMResult</code>s.
|
||||
* <p>This implementation delegates to <code>marshalDomNode</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param domResult the <code>DOMResult</code>
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @throws IllegalArgumentException if the <code>domResult</code> is empty
|
||||
* @see #marshalDomNode(Object, org.w3c.dom.Node)
|
||||
*/
|
||||
protected void marshalDomResult(Object graph, DOMResult domResult) throws XmlMappingException {
|
||||
if (domResult.getNode() == null) {
|
||||
try {
|
||||
synchronized (this.documentBuilderFactoryMonitor) {
|
||||
if (this.documentBuilderFactory == null) {
|
||||
this.documentBuilderFactory = createDocumentBuilderFactory();
|
||||
}
|
||||
}
|
||||
DocumentBuilder documentBuilder = createDocumentBuilder(this.documentBuilderFactory);
|
||||
domResult.setNode(documentBuilder.newDocument());
|
||||
}
|
||||
catch (ParserConfigurationException ex) {
|
||||
throw new UnmarshallingFailureException(
|
||||
"Could not create document placeholder for DOMResult: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
marshalDomNode(graph, domResult.getNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>StaxResult</code>s.
|
||||
* <p>This implementation delegates to <code>marshalXMLSteamWriter</code> or
|
||||
* <code>marshalXMLEventConsumer</code>, depending on what is contained in the
|
||||
* <code>StaxResult</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param staxResult a Spring {@link org.springframework.util.xml.StaxSource} or JAXP 1.4 {@link StAXSource}
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @throws IllegalArgumentException if the <code>domResult</code> is empty
|
||||
* @see #marshalDomNode(Object,org.w3c.dom.Node)
|
||||
*/
|
||||
protected void marshalStaxResult(Object graph, Result staxResult) throws XmlMappingException {
|
||||
XMLStreamWriter streamWriter = StaxUtils.getXMLStreamWriter(staxResult);
|
||||
if (streamWriter != null) {
|
||||
marshalXmlStreamWriter(graph, streamWriter);
|
||||
}
|
||||
else {
|
||||
XMLEventWriter eventWriter = StaxUtils.getXMLEventWriter(staxResult);
|
||||
if (eventWriter != null) {
|
||||
marshalXmlEventWriter(graph, eventWriter);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StaxResult contains neither XMLStreamWriter nor XMLEventConsumer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>SAXResult</code>s.
|
||||
* <p>This implementation delegates to <code>marshalSaxHandlers</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param saxResult the <code>SAXResult</code>
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @see #marshalSaxHandlers(Object, org.xml.sax.ContentHandler, org.xml.sax.ext.LexicalHandler)
|
||||
*/
|
||||
protected void marshalSaxResult(Object graph, SAXResult saxResult) throws XmlMappingException {
|
||||
ContentHandler contentHandler = saxResult.getHandler();
|
||||
Assert.notNull(contentHandler, "ContentHandler not set on SAXResult");
|
||||
LexicalHandler lexicalHandler = saxResult.getLexicalHandler();
|
||||
marshalSaxHandlers(graph, contentHandler, lexicalHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>StreamResult</code>s.
|
||||
* <p>This implementation delegates to <code>marshalOutputStream</code> or <code>marshalWriter</code>,
|
||||
* depending on what is contained in the <code>StreamResult</code>
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param streamResult the <code>StreamResult</code>
|
||||
* @throws IOException if an I/O Exception occurs
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the result
|
||||
* @throws IllegalArgumentException if <code>streamResult</code> does neither
|
||||
* contain an <code>OutputStream</code> nor a <code>Writer</code>
|
||||
*/
|
||||
protected void marshalStreamResult(Object graph, StreamResult streamResult)
|
||||
throws XmlMappingException, IOException {
|
||||
|
||||
if (streamResult.getOutputStream() != null) {
|
||||
marshalOutputStream(graph, streamResult.getOutputStream());
|
||||
}
|
||||
else if (streamResult.getWriter() != null) {
|
||||
marshalWriter(graph, streamResult.getWriter());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StreamResult contains neither OutputStream nor Writer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
/**
|
||||
* Template method for handling <code>DOMSource</code>s.
|
||||
* <p>This implementation delegates to <code>unmarshalDomNode</code>.
|
||||
* If the given source is empty, an empty source <code>Document</code>
|
||||
* will be created as a placeholder.
|
||||
* @param domSource the <code>DOMSource</code>
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
* @throws IllegalArgumentException if the <code>domSource</code> is empty
|
||||
* @see #unmarshalDomNode(org.w3c.dom.Node)
|
||||
*/
|
||||
protected Object unmarshalDomSource(DOMSource domSource) throws XmlMappingException {
|
||||
if (domSource.getNode() == null) {
|
||||
try {
|
||||
synchronized (this.documentBuilderFactoryMonitor) {
|
||||
if (this.documentBuilderFactory == null) {
|
||||
this.documentBuilderFactory = createDocumentBuilderFactory();
|
||||
}
|
||||
}
|
||||
DocumentBuilder documentBuilder = createDocumentBuilder(this.documentBuilderFactory);
|
||||
domSource.setNode(documentBuilder.newDocument());
|
||||
}
|
||||
catch (ParserConfigurationException ex) {
|
||||
throw new UnmarshallingFailureException(
|
||||
"Could not create document placeholder for DOMSource: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
return unmarshalDomNode(domSource.getNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>StaxSource</code>s.
|
||||
* <p>This implementation delegates to <code>unmarshalXmlStreamReader</code> or
|
||||
* <code>unmarshalXmlEventReader</code>.
|
||||
* @param staxSource the <code>StaxSource</code>
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
*/
|
||||
protected Object unmarshalStaxSource(Source staxSource) throws XmlMappingException {
|
||||
XMLStreamReader streamReader = StaxUtils.getXMLStreamReader(staxSource);
|
||||
if (streamReader != null) {
|
||||
return unmarshalXmlStreamReader(streamReader);
|
||||
}
|
||||
else {
|
||||
XMLEventReader eventReader = StaxUtils.getXMLEventReader(staxSource);
|
||||
if (eventReader != null) {
|
||||
return unmarshalXmlEventReader(eventReader);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StaxSource contains neither XMLStreamReader nor XMLEventReader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>SAXSource</code>s.
|
||||
* <p>This implementation delegates to <code>unmarshalSaxReader</code>.
|
||||
* @param saxSource the <code>SAXSource</code>
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
* @throws IOException if an I/O Exception occurs
|
||||
* @see #unmarshalSaxReader(org.xml.sax.XMLReader, org.xml.sax.InputSource)
|
||||
*/
|
||||
protected Object unmarshalSaxSource(SAXSource saxSource) throws XmlMappingException, IOException {
|
||||
if (saxSource.getXMLReader() == null) {
|
||||
try {
|
||||
saxSource.setXMLReader(createXmlReader());
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
throw new UnmarshallingFailureException("Could not create XMLReader for SAXSource", ex);
|
||||
}
|
||||
}
|
||||
if (saxSource.getInputSource() == null) {
|
||||
saxSource.setInputSource(new InputSource());
|
||||
}
|
||||
return unmarshalSaxReader(saxSource.getXMLReader(), saxSource.getInputSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for handling <code>StreamSource</code>s.
|
||||
* <p>This implementation defers to <code>unmarshalInputStream</code> or <code>unmarshalReader</code>.
|
||||
* @param streamSource the <code>StreamSource</code>
|
||||
* @return the object graph
|
||||
* @throws IOException if an I/O exception occurs
|
||||
* @throws XmlMappingException if the given source cannot be mapped to an object
|
||||
*/
|
||||
protected Object unmarshalStreamSource(StreamSource streamSource) throws XmlMappingException, IOException {
|
||||
if (streamSource.getInputStream() != null) {
|
||||
return unmarshalInputStream(streamSource.getInputStream());
|
||||
}
|
||||
else if (streamSource.getReader() != null) {
|
||||
return unmarshalReader(streamSource.getReader());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Abstract template methods
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object graph to a DOM <code>Node</code>.
|
||||
* <p>In practice, node is be a <code>Document</code> node, a <code>DocumentFragment</code> node,
|
||||
* or a <code>Element</code> node. In other words, a node that accepts children.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param node the DOM node that will contain the result tree
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the DOM node
|
||||
* @see org.w3c.dom.Document
|
||||
* @see org.w3c.dom.DocumentFragment
|
||||
* @see org.w3c.dom.Element
|
||||
*/
|
||||
protected abstract void marshalDomNode(Object graph, Node node)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object to a StAX <code>XMLEventWriter</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param eventWriter the <code>XMLEventWriter</code> to write to
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the DOM node
|
||||
*/
|
||||
protected abstract void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object to a StAX <code>XMLStreamWriter</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param streamWriter the <code>XMLStreamWriter</code> to write to
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the DOM node
|
||||
*/
|
||||
protected abstract void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object graph to a <code>OutputStream</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param outputStream the <code>OutputStream</code> to write to
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the writer
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected abstract void marshalOutputStream(Object graph, OutputStream outputStream)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object graph to a SAX <code>ContentHandler</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param contentHandler the SAX <code>ContentHandler</code>
|
||||
* @param lexicalHandler the SAX2 <code>LexicalHandler</code>. Can be <code>null</code>.
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the handlers
|
||||
*/
|
||||
protected abstract void marshalSaxHandlers(
|
||||
Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for marshalling the given object graph to a <code>Writer</code>.
|
||||
* @param graph the root of the object graph to marshal
|
||||
* @param writer the <code>Writer</code> to write to
|
||||
* @throws XmlMappingException if the given object cannot be marshalled to the writer
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected abstract void marshalWriter(Object graph, Writer writer)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling from a given DOM <code>Node</code>.
|
||||
* @param node the DOM node that contains the objects to be unmarshalled
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given DOM node cannot be mapped to an object
|
||||
*/
|
||||
protected abstract Object unmarshalDomNode(Node node) throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling from a given Stax <code>XMLEventReader</code>.
|
||||
* @param eventReader the <code>XMLEventReader</code> to read from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given event reader cannot be converted to an object
|
||||
*/
|
||||
protected abstract Object unmarshalXmlEventReader(XMLEventReader eventReader)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling from a given Stax <code>XMLStreamReader</code>.
|
||||
* @param streamReader the <code>XMLStreamReader</code> to read from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given stream reader cannot be converted to an object
|
||||
*/
|
||||
protected abstract Object unmarshalXmlStreamReader(XMLStreamReader streamReader)
|
||||
throws XmlMappingException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling from a given <code>InputStream</code>.
|
||||
* @param inputStream the <code>InputStreamStream</code> to read from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given stream cannot be converted to an object
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected abstract Object unmarshalInputStream(InputStream inputStream)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling from a given <code>Reader</code>.
|
||||
* @param reader the <code>Reader</code> to read from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given reader cannot be converted to an object
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected abstract Object unmarshalReader(Reader reader)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
/**
|
||||
* Abstract template method for unmarshalling using a given SAX <code>XMLReader</code>
|
||||
* and <code>InputSource</code>.
|
||||
* @param xmlReader the SAX <code>XMLReader</code> to parse with
|
||||
* @param inputSource the input source to parse from
|
||||
* @return the object graph
|
||||
* @throws XmlMappingException if the given reader and input source cannot be converted to an object
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected abstract Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.DTDHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Source} implementation that uses a {@link Marshaller}.Can be constructed with a
|
||||
* <code>Marshaller</code> and an object to be marshalled.
|
||||
*
|
||||
* <p>Even though <code>MarshallingSource</code> extends from <code>SAXSource</code>, calling the methods of
|
||||
* <code>SAXSource</code> is <strong>not supported</strong>. In general, the only supported operation on this class is
|
||||
* to use the <code>XMLReader</code> obtained via {@link #getXMLReader()} to parse the input source obtained via {@link
|
||||
* #getInputSource()}. Calling {@link #setXMLReader(XMLReader)} or {@link #setInputSource(InputSource)} will result in
|
||||
* <code>UnsupportedOperationException</code>s.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see javax.xml.transform.Transformer
|
||||
*/
|
||||
public class MarshallingSource extends SAXSource {
|
||||
|
||||
private final Marshaller marshaller;
|
||||
|
||||
private final Object content;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new <code>MarshallingSource</code> with the given marshaller and content.
|
||||
* @param marshaller the marshaller to use
|
||||
* @param content the object to be marshalled
|
||||
*/
|
||||
public MarshallingSource(Marshaller marshaller, Object content) {
|
||||
super(new MarshallingXMLReader(marshaller, content), new InputSource());
|
||||
Assert.notNull(marshaller, "'marshaller' must not be null");
|
||||
Assert.notNull(content, "'content' must not be null");
|
||||
this.marshaller = marshaller;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the <code>Marshaller</code> used by this <code>MarshallingSource</code>.
|
||||
*/
|
||||
public Marshaller getMarshaller() {
|
||||
return this.marshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object to be marshalled.
|
||||
*/
|
||||
public Object getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a <code>UnsupportedOperationException</code>.
|
||||
*/
|
||||
@Override
|
||||
public void setInputSource(InputSource inputSource) {
|
||||
throw new UnsupportedOperationException("setInputSource is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a <code>UnsupportedOperationException</code>.
|
||||
*/
|
||||
@Override
|
||||
public void setXMLReader(XMLReader reader) {
|
||||
throw new UnsupportedOperationException("setXMLReader is not supported");
|
||||
}
|
||||
|
||||
|
||||
private static class MarshallingXMLReader implements XMLReader {
|
||||
|
||||
private final Marshaller marshaller;
|
||||
|
||||
private final Object content;
|
||||
|
||||
private DTDHandler dtdHandler;
|
||||
|
||||
private ContentHandler contentHandler;
|
||||
|
||||
private EntityResolver entityResolver;
|
||||
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
private LexicalHandler lexicalHandler;
|
||||
|
||||
private MarshallingXMLReader(Marshaller marshaller, Object content) {
|
||||
Assert.notNull(marshaller, "'marshaller' must not be null");
|
||||
Assert.notNull(content, "'content' must not be null");
|
||||
this.marshaller = marshaller;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public void setContentHandler(ContentHandler contentHandler) {
|
||||
this.contentHandler = contentHandler;
|
||||
}
|
||||
|
||||
public ContentHandler getContentHandler() {
|
||||
return this.contentHandler;
|
||||
}
|
||||
|
||||
public void setDTDHandler(DTDHandler dtdHandler) {
|
||||
this.dtdHandler = dtdHandler;
|
||||
}
|
||||
|
||||
public DTDHandler getDTDHandler() {
|
||||
return this.dtdHandler;
|
||||
}
|
||||
|
||||
public void setEntityResolver(EntityResolver entityResolver) {
|
||||
this.entityResolver = entityResolver;
|
||||
}
|
||||
|
||||
public EntityResolver getEntityResolver() {
|
||||
return this.entityResolver;
|
||||
}
|
||||
|
||||
public void setErrorHandler(ErrorHandler errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public ErrorHandler getErrorHandler() {
|
||||
return this.errorHandler;
|
||||
}
|
||||
|
||||
protected LexicalHandler getLexicalHandler() {
|
||||
return this.lexicalHandler;
|
||||
}
|
||||
|
||||
public boolean getFeature(String name) throws SAXNotRecognizedException {
|
||||
throw new SAXNotRecognizedException(name);
|
||||
}
|
||||
|
||||
public void setFeature(String name, boolean value) throws SAXNotRecognizedException {
|
||||
throw new SAXNotRecognizedException(name);
|
||||
}
|
||||
|
||||
public Object getProperty(String name) throws SAXNotRecognizedException {
|
||||
if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
|
||||
return lexicalHandler;
|
||||
}
|
||||
else {
|
||||
throw new SAXNotRecognizedException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProperty(String name, Object value) throws SAXNotRecognizedException {
|
||||
if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
|
||||
this.lexicalHandler = (LexicalHandler) value;
|
||||
}
|
||||
else {
|
||||
throw new SAXNotRecognizedException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void parse(InputSource input) throws SAXException {
|
||||
parse();
|
||||
}
|
||||
|
||||
public void parse(String systemId) throws SAXException {
|
||||
parse();
|
||||
}
|
||||
|
||||
private void parse() throws SAXException {
|
||||
SAXResult result = new SAXResult(getContentHandler());
|
||||
result.setLexicalHandler(getLexicalHandler());
|
||||
try {
|
||||
this.marshaller.marshal(this.content, result);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
SAXParseException saxException = new SAXParseException(ex.getMessage(), null, null, -1, -1, ex);
|
||||
ErrorHandler errorHandler = getErrorHandler();
|
||||
if (errorHandler != null) {
|
||||
errorHandler.fatalError(saxException);
|
||||
}
|
||||
else {
|
||||
throw saxException;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.support;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Convenient utility methods for dealing with SAX.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class SaxResourceUtils {
|
||||
|
||||
/**
|
||||
* Create a SAX <code>InputSource</code> from the given resource.
|
||||
* <p>Sets the system identifier to the resource's <code>URL</code>, if available.
|
||||
* @param resource the resource
|
||||
* @return the input source created from the resource
|
||||
* @throws IOException if an I/O exception occurs
|
||||
* @see InputSource#setSystemId(String)
|
||||
* @see #getSystemId(org.springframework.core.io.Resource)
|
||||
*/
|
||||
public static InputSource createInputSource(Resource resource) throws IOException {
|
||||
InputSource inputSource = new InputSource(resource.getInputStream());
|
||||
inputSource.setSystemId(getSystemId(resource));
|
||||
return inputSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the URL from the given resource as System ID.
|
||||
* <p>Returns <code>null</code> if it cannot be opened.
|
||||
*/
|
||||
private static String getSystemId(Resource resource) {
|
||||
try {
|
||||
return resource.getURI().toString();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides generic support classes for using Spring's O/X Mapping integration within various scenario's. Includes the
|
||||
* MarshallingSource for compatibility with TrAX, MarshallingView for use withing Spring Web MVC, and the
|
||||
* MarshallingMessageConverter for use within Spring's JMS support.
|
||||
* </htm
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.support;
|
||||
|
||||
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xmlbeans;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.io.FilterInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.CharBuffer;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
import org.apache.xmlbeans.XMLStreamValidationException;
|
||||
import org.apache.xmlbeans.XmlError;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.apache.xmlbeans.XmlSaxHandler;
|
||||
import org.apache.xmlbeans.XmlValidationError;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
import org.springframework.oxm.Marshaller;
|
||||
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.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link Marshaller} interface for Apache XMLBeans.
|
||||
*
|
||||
* <p>Options can be set by setting the <code>xmlOptions</code> property.
|
||||
* The {@link XmlOptionsFactoryBean} is provided to easily set up an {@link XmlOptions} instance.
|
||||
*
|
||||
* <p>Unmarshalled objects can be validated by setting the <code>validating</code> property,
|
||||
* or by calling the {@link #validate(XmlObject)} method directly. Invalid objects will
|
||||
* result in an {@link ValidationFailureException}.
|
||||
*
|
||||
* <p><b>NOTE:</b> Due to the nature of XMLBeans, this marshaller requires
|
||||
* all passed objects to be of type {@link XmlObject}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see #setValidating
|
||||
* @see #setXmlOptions
|
||||
* @see XmlOptionsFactoryBean
|
||||
*/
|
||||
public class XmlBeansMarshaller extends AbstractMarshaller {
|
||||
|
||||
private XmlOptions xmlOptions;
|
||||
|
||||
private boolean validating = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set the <code>XmlOptions</code>.
|
||||
* @see XmlOptionsFactoryBean
|
||||
*/
|
||||
public void setXmlOptions(XmlOptions xmlOptions) {
|
||||
this.xmlOptions = xmlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the <code>XmlOptions</code>.
|
||||
*/
|
||||
public XmlOptions getXmlOptions() {
|
||||
return this.xmlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this marshaller should validate in- and outgoing documents.
|
||||
* Default is <code>false</code>.
|
||||
*/
|
||||
public void setValidating(boolean validating) {
|
||||
this.validating = validating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this marshaller should validate in- and outgoing documents.
|
||||
*/
|
||||
public boolean isValidating() {
|
||||
return this.validating;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation returns true if the given class is an implementation of {@link XmlObject}.
|
||||
*/
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return XmlObject.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalDomNode(Object graph, Node node) throws XmlMappingException {
|
||||
Document document = node.getNodeType() == Node.DOCUMENT_NODE ? (Document) node : node.getOwnerDocument();
|
||||
Node xmlBeansNode = ((XmlObject) graph).newDomNode(getXmlOptions());
|
||||
NodeList xmlBeansChildNodes = xmlBeansNode.getChildNodes();
|
||||
for (int i = 0; i < xmlBeansChildNodes.getLength(); i++) {
|
||||
Node xmlBeansChildNode = xmlBeansChildNodes.item(i);
|
||||
Node importedNode = document.importNode(xmlBeansChildNode, true);
|
||||
node.appendChild(importedNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalOutputStream(Object graph, OutputStream outputStream)
|
||||
throws XmlMappingException, IOException {
|
||||
|
||||
((XmlObject) graph).save(outputStream, getXmlOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
|
||||
throws XmlMappingException {
|
||||
try {
|
||||
((XmlObject) graph).save(contentHandler, lexicalHandler, getXmlOptions());
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
throw convertXmlBeansException(ex, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
|
||||
((XmlObject) graph).save(writer, getXmlOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) {
|
||||
ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter);
|
||||
marshalSaxHandlers(graph, contentHandler, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
|
||||
ContentHandler contentHandler = StaxUtils.createContentHandler(streamWriter);
|
||||
marshalSaxHandlers(graph, contentHandler, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalDomNode(Node node) throws XmlMappingException {
|
||||
try {
|
||||
XmlObject object = XmlObject.Factory.parse(node, getXmlOptions());
|
||||
validate(object);
|
||||
return object;
|
||||
}
|
||||
catch (XmlException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
|
||||
try {
|
||||
InputStream nonClosingInputStream = new NonClosingInputStream(inputStream);
|
||||
XmlObject object = XmlObject.Factory.parse(nonClosingInputStream, getXmlOptions());
|
||||
validate(object);
|
||||
return object;
|
||||
}
|
||||
catch (XmlException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
|
||||
try {
|
||||
Reader nonClosingReader = new NonClosingReader(reader);
|
||||
XmlObject object = XmlObject.Factory.parse(nonClosingReader, getXmlOptions());
|
||||
validate(object);
|
||||
return object;
|
||||
}
|
||||
catch (XmlException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
|
||||
throws XmlMappingException, IOException {
|
||||
XmlSaxHandler saxHandler = XmlObject.Factory.newXmlSaxHandler(getXmlOptions());
|
||||
xmlReader.setContentHandler(saxHandler.getContentHandler());
|
||||
try {
|
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", saxHandler.getLexicalHandler());
|
||||
}
|
||||
catch (SAXNotRecognizedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (SAXNotSupportedException e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
xmlReader.parse(inputSource);
|
||||
XmlObject object = saxHandler.getObject();
|
||||
validate(object);
|
||||
return object;
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
catch (XmlException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException {
|
||||
XMLReader reader = StaxUtils.createXMLReader(eventReader);
|
||||
try {
|
||||
return unmarshalSaxReader(reader, new InputSource());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException {
|
||||
try {
|
||||
XmlObject object = XmlObject.Factory.parse(streamReader, getXmlOptions());
|
||||
validate(object);
|
||||
return object;
|
||||
}
|
||||
catch (XmlException ex) {
|
||||
throw convertXmlBeansException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the given <code>XmlObject</code>.
|
||||
* @param object the xml object to validate
|
||||
* @throws ValidationFailureException if the given object is not valid
|
||||
*/
|
||||
protected void validate(XmlObject object) throws ValidationFailureException {
|
||||
if (isValidating() && object != null) {
|
||||
// create a temporary xmlOptions just for validation
|
||||
XmlOptions validateOptions = getXmlOptions() != null ? getXmlOptions() : new XmlOptions();
|
||||
List errorsList = new ArrayList();
|
||||
validateOptions.setErrorListener(errorsList);
|
||||
if (!object.validate(validateOptions)) {
|
||||
StringBuilder builder = new StringBuilder("Could not validate XmlObject :");
|
||||
for (Object anErrorsList : errorsList) {
|
||||
XmlError xmlError = (XmlError) anErrorsList;
|
||||
if (xmlError instanceof XmlValidationError) {
|
||||
builder.append(xmlError.toString());
|
||||
}
|
||||
}
|
||||
throw new ValidationFailureException("XMLBeans validation failure",
|
||||
new XmlException(builder.toString(), null, errorsList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given XMLBeans exception to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> hierarchy.
|
||||
* <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
|
||||
* unmarshalling, since XMLBeans itself does not make this distinction in its exception hierarchy.
|
||||
* @param ex XMLBeans Exception that occured
|
||||
* @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
|
||||
* or unmarshalling (<code>false</code>)
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
protected XmlMappingException convertXmlBeansException(Exception ex, boolean marshalling) {
|
||||
if (ex instanceof XMLStreamValidationException) {
|
||||
return new ValidationFailureException("XmlBeans validation exception", ex);
|
||||
}
|
||||
else if (ex instanceof XmlException || ex instanceof SAXException) {
|
||||
if (marshalling) {
|
||||
return new MarshallingFailureException("XMLBeans marshalling exception", ex);
|
||||
}
|
||||
else {
|
||||
return new UnmarshallingFailureException("XMLBeans unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
return new UncategorizedMappingException("Unknown XMLBeans exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See SPR-7034
|
||||
*/
|
||||
private static class NonClosingInputStream extends InputStream {
|
||||
|
||||
private final WeakReference<InputStream> in;
|
||||
|
||||
private NonClosingInputStream(InputStream in) {
|
||||
this.in = new WeakReference<InputStream>(in);
|
||||
}
|
||||
|
||||
private InputStream getInputStream() {
|
||||
return this.in.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
return in != null ? in.read() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
return in != null ? in.read(b) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
return in != null ? in.read(b, off, len) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
return in != null ? in.skip(n) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
InputStream in = getInputStream();
|
||||
return in != null && in.markSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
InputStream in = getInputStream();
|
||||
if (in != null) {
|
||||
in.mark(readlimit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
if (in != null) {
|
||||
in.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
return in != null ? in.available() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
InputStream in = getInputStream();
|
||||
if(in != null) {
|
||||
this.in.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NonClosingReader extends Reader {
|
||||
|
||||
private final WeakReference<Reader> reader;
|
||||
|
||||
private NonClosingReader(Reader reader) {
|
||||
this.reader = new WeakReference<Reader>(reader);
|
||||
}
|
||||
|
||||
private Reader getReader() {
|
||||
return this.reader.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(CharBuffer target) throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null ? rdr.read(target) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null ? rdr.read() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(char[] cbuf) throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null ? rdr.read(cbuf) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null ? rdr.read(cbuf, off, len) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null ? rdr.skip(n) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ready() throws IOException {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null && rdr.ready();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
Reader rdr = getReader();
|
||||
return rdr != null && rdr.markSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readAheadLimit) throws IOException {
|
||||
Reader rdr = getReader();
|
||||
if (rdr != null) {
|
||||
rdr.mark(readAheadLimit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
Reader rdr = getReader();
|
||||
if (rdr != null) {
|
||||
rdr.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
Reader rdr = getReader();
|
||||
if (rdr != null) {
|
||||
this.reader.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xmlbeans;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that configures an XMLBeans <code>XmlOptions</code> object
|
||||
* and provides it as a bean reference.
|
||||
*
|
||||
* <p>Typical usage will be to set XMLBeans options on this bean, and refer to it
|
||||
* in the {@link XmlBeansMarshaller}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see XmlOptions
|
||||
* @see #setOptions(java.util.Map)
|
||||
* @see XmlBeansMarshaller#setXmlOptions(XmlOptions)
|
||||
*/
|
||||
public class XmlOptionsFactoryBean implements FactoryBean<XmlOptions> {
|
||||
|
||||
private XmlOptions xmlOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Set options on the underlying <code>XmlOptions</code> object.
|
||||
* <p>The keys of the supplied map should be one of the String constants
|
||||
* defined in <code>XmlOptions</code>, the values vary per option.
|
||||
* @see XmlOptions#put(Object,Object)
|
||||
* @see XmlOptions#SAVE_PRETTY_PRINT
|
||||
* @see XmlOptions#LOAD_STRIP_COMMENTS
|
||||
*/
|
||||
public void setOptions(Map<String, ?> optionsMap) {
|
||||
this.xmlOptions = new XmlOptions();
|
||||
if (optionsMap != null) {
|
||||
for (String option : optionsMap.keySet()) {
|
||||
this.xmlOptions.put(option, optionsMap.get(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public XmlOptions getObject() {
|
||||
return this.xmlOptions;
|
||||
}
|
||||
|
||||
public Class<? extends XmlOptions> getObjectType() {
|
||||
return XmlOptions.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package providing integration of <a href="http://xmlbeans.apache.org/">XMLBeans</a> with Springs O/X Mapping support
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.xmlbeans;
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.xstream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.converters.ConversionException;
|
||||
import com.thoughtworks.xstream.converters.Converter;
|
||||
import com.thoughtworks.xstream.converters.ConverterMatcher;
|
||||
import com.thoughtworks.xstream.converters.SingleValueConverter;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.StreamException;
|
||||
import com.thoughtworks.xstream.io.xml.CompactWriter;
|
||||
import com.thoughtworks.xstream.io.xml.DomReader;
|
||||
import com.thoughtworks.xstream.io.xml.DomWriter;
|
||||
import com.thoughtworks.xstream.io.xml.QNameMap;
|
||||
import com.thoughtworks.xstream.io.xml.SaxWriter;
|
||||
import com.thoughtworks.xstream.io.xml.StaxReader;
|
||||
import com.thoughtworks.xstream.io.xml.StaxWriter;
|
||||
import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer;
|
||||
import com.thoughtworks.xstream.io.xml.XppReader;
|
||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
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.oxm.MarshallingFailureException;
|
||||
import org.springframework.oxm.UncategorizedMappingException;
|
||||
import org.springframework.oxm.UnmarshallingFailureException;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.oxm.support.AbstractMarshaller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>Marshaller</code> interface for XStream.
|
||||
*
|
||||
* <p>By default, XStream does not require any further configuration,
|
||||
* though class aliases can be used to have more control over the behavior of XStream.
|
||||
*
|
||||
* <p>Due to XStream's API, it is required to set the encoding used for writing to OutputStreams.
|
||||
* It defaults to <code>UTF-8</code>.
|
||||
*
|
||||
* <p><b>NOTE:</b> XStream is an XML serialization library, not a data binding library.
|
||||
* Therefore, it has limited namespace support. As such, it is rather unsuitable for
|
||||
* usage within Web services.
|
||||
*
|
||||
* @author Peter Meijer
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see #setAliases
|
||||
* @see #setConverters
|
||||
* @see #setEncoding
|
||||
*/
|
||||
public class XStreamMarshaller extends AbstractMarshaller implements InitializingBean, BeanClassLoaderAware {
|
||||
|
||||
/**
|
||||
* The default encoding used for stream access: UTF-8.
|
||||
*/
|
||||
public static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
|
||||
private final XStream xstream = new XStream();
|
||||
|
||||
private HierarchicalStreamDriver streamDriver;
|
||||
|
||||
private String encoding = DEFAULT_ENCODING;
|
||||
|
||||
private Class[] supportedClasses;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the XStream instance used by this marshaller.
|
||||
*/
|
||||
public XStream getXStream() {
|
||||
return this.xstream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the XStream mode.
|
||||
* @see XStream#XPATH_REFERENCES
|
||||
* @see XStream#ID_REFERENCES
|
||||
* @see XStream#NO_REFERENCES
|
||||
*/
|
||||
public void setMode(int mode) {
|
||||
this.getXStream().setMode(mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>Converters</code> or <code>SingleValueConverters</code> to be registered
|
||||
* with the <code>XStream</code> instance.
|
||||
* @see Converter
|
||||
* @see SingleValueConverter
|
||||
*/
|
||||
public void setConverters(ConverterMatcher[] converters) {
|
||||
for (int i = 0; i < converters.length; i++) {
|
||||
if (converters[i] instanceof Converter) {
|
||||
this.getXStream().registerConverter((Converter) converters[i], i);
|
||||
}
|
||||
else if (converters[i] instanceof SingleValueConverter) {
|
||||
this.getXStream().registerConverter((SingleValueConverter) converters[i], i);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid ConverterMatcher [" + converters[i] + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alias/type map, consisting of string aliases mapped to classes. Keys are aliases; values are either
|
||||
* {@code Class} instances, or String class names.
|
||||
* @see XStream#alias(String, Class)
|
||||
*/
|
||||
public void setAliases(Map<String, ?> aliases) throws ClassNotFoundException {
|
||||
Map<String, Class<?>> classMap = toClassMap(aliases);
|
||||
|
||||
for (Map.Entry<String, Class<?>> entry : classMap.entrySet()) {
|
||||
this.getXStream().alias(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the aliases by type map, consisting of string aliases mapped to classes. Any class that is assignable to
|
||||
* this type will be aliased to the same name. Keys are aliases; values are either
|
||||
* {@code Class} instances, or String class names.
|
||||
* @see XStream#aliasType(String, Class)
|
||||
*/
|
||||
public void setAliasesByType(Map<String, ?> aliases) throws ClassNotFoundException {
|
||||
Map<String, Class<?>> classMap = toClassMap(aliases);
|
||||
|
||||
for (Map.Entry<String, Class<?>> entry : classMap.entrySet()) {
|
||||
this.getXStream().aliasType(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Class<?>> toClassMap(Map<String, ?> map) throws ClassNotFoundException {
|
||||
Map<String, Class<?>> result = new LinkedHashMap<String, Class<?>>(map.size());
|
||||
|
||||
for (Map.Entry<String, ?> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
Class type;
|
||||
if (value instanceof Class) {
|
||||
type = (Class) value;
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
String s = (String) value;
|
||||
type = ClassUtils.forName(s, classLoader);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown value [" + value + "], expected String or Class");
|
||||
}
|
||||
result.put(key, type);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a field alias/type map, consiting of field names
|
||||
* @param aliases
|
||||
* @throws ClassNotFoundException
|
||||
* @throws NoSuchFieldException
|
||||
* @see XStream#aliasField(String, Class, String)
|
||||
*/
|
||||
public void setFieldAliases(Map<String, String> aliases) throws ClassNotFoundException, NoSuchFieldException {
|
||||
for (Map.Entry<String, String> entry : aliases.entrySet()) {
|
||||
String alias = entry.getValue();
|
||||
String field = entry.getKey();
|
||||
int idx = field.lastIndexOf('.');
|
||||
if (idx != -1) {
|
||||
String className = field.substring(0, idx);
|
||||
Class clazz = ClassUtils.forName(className, classLoader);
|
||||
String fieldName = field.substring(idx + 1);
|
||||
this.getXStream().aliasField(alias, clazz, fieldName);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Field name [" + field + "] does not contain '.'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set types to use XML attributes for.
|
||||
* @see XStream#useAttributeFor(Class)
|
||||
*/
|
||||
public void setUseAttributeForTypes(Class[] types) {
|
||||
for (Class type : types) {
|
||||
this.getXStream().useAttributeFor(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the types to use XML attributes for. The given map can contain
|
||||
* either {@code <String, Class>} pairs, in which case
|
||||
* {@link XStream#useAttributeFor(String, Class)} is called.
|
||||
* Alternatively, the map can contain {@code <Class, String>}
|
||||
* or {@code <Class, List<String>>} pairs, which results in
|
||||
* {@link XStream#useAttributeFor(Class, String)} calls.
|
||||
*/
|
||||
public void setUseAttributeFor(Map<?, ?> attributes) {
|
||||
for (Map.Entry<?, ?> entry : attributes.entrySet()) {
|
||||
if (entry.getKey() instanceof String) {
|
||||
if (entry.getValue() instanceof Class) {
|
||||
this.getXStream().useAttributeFor((String) entry.getKey(), (Class) entry.getValue());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid argument 'attributes'. 'useAttributesFor' property takes map of <String, Class>," +
|
||||
" when using a map key of type String");
|
||||
}
|
||||
}
|
||||
else if (entry.getKey() instanceof Class) {
|
||||
Class<?> key = (Class<?>) entry.getKey();
|
||||
if (entry.getValue() instanceof String) {
|
||||
this.getXStream().useAttributeFor(key, (String) entry.getValue());
|
||||
}
|
||||
else if (entry.getValue() instanceof List) {
|
||||
List list = (List) entry.getValue();
|
||||
|
||||
for (Object o : list) {
|
||||
if (o instanceof String) {
|
||||
this.getXStream().useAttributeFor(key, (String) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid argument 'attributes'. " +
|
||||
"'useAttributesFor' property takes either <Class, String> or <Class, List<String>> map," +
|
||||
" when using a map key of type Class");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid argument 'attributes. " +
|
||||
"'useAttributesFor' property takes either a map key of type String or Class");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify implicit collection fields, as a Map consisting of <code>Class</code> instances
|
||||
* mapped to comma separated collection field names.
|
||||
*@see XStream#addImplicitCollection(Class, String)
|
||||
*/
|
||||
public void setImplicitCollections(Map<Class<?>, String> implicitCollections) {
|
||||
for (Map.Entry<Class<?>, String> entry : implicitCollections.entrySet()) {
|
||||
String[] collectionFields = StringUtils.commaDelimitedListToStringArray(entry.getValue());
|
||||
for (String collectionField : collectionFields) {
|
||||
this.getXStream().addImplicitCollection(entry.getKey(), collectionField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify omitted fields, as a Map consisting of <code>Class</code> instances
|
||||
* mapped to comma separated field names.
|
||||
* @see XStream#omitField(Class, String)
|
||||
*/
|
||||
public void setOmittedFields(Map<Class<?>, String> omittedFields) {
|
||||
for (Map.Entry<Class<?>, String> entry : omittedFields.entrySet()) {
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(entry.getValue());
|
||||
for (String field : fields) {
|
||||
this.getXStream().omitField(entry.getKey(), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the classes for which mappings will be read from class-level JDK 1.5+ annotation metadata.
|
||||
* @see XStream#processAnnotations(Class)
|
||||
*/
|
||||
public void setAnnotatedClass(Class<?> annotatedClass) {
|
||||
Assert.notNull(annotatedClass, "'annotatedClass' must not be null");
|
||||
this.getXStream().processAnnotations(annotatedClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set annotated classes for which aliases will be read from class-level JDK 1.5+ annotation metadata.
|
||||
* @see XStream#processAnnotations(Class[])
|
||||
*/
|
||||
public void setAnnotatedClasses(Class<?>[] annotatedClasses) {
|
||||
Assert.notEmpty(annotatedClasses, "'annotatedClasses' must not be empty");
|
||||
this.getXStream().processAnnotations(annotatedClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the autodetection mode of XStream.
|
||||
* <p><strong>Note</strong> that auto-detection implies that the XStream is configured while
|
||||
* it is processing the XML streams, and thus introduces a potential concurrency problem.
|
||||
* @see XStream#autodetectAnnotations(boolean)
|
||||
*/
|
||||
public void setAutodetectAnnotations(boolean autodetectAnnotations) {
|
||||
this.getXStream().autodetectAnnotations(autodetectAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the XStream hierarchical stream driver to be used with stream readers and writers.
|
||||
*/
|
||||
public void setStreamDriver(HierarchicalStreamDriver streamDriver) {
|
||||
this.streamDriver = streamDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encoding to be used for stream access.
|
||||
* @see #DEFAULT_ENCODING
|
||||
*/
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the classes supported by this marshaller.
|
||||
* <p>If this property is empty (the default), all classes are supported.
|
||||
* @see #supports(Class)
|
||||
*/
|
||||
public void setSupportedClasses(Class[] supportedClasses) {
|
||||
this.supportedClasses = supportedClasses;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
customizeXStream(getXStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to allow for customizing of the given {@link XStream}.
|
||||
* <p>The default implementation is empty.
|
||||
* @param xstream the {@code XStream} instance
|
||||
*/
|
||||
protected void customizeXStream(XStream xstream) {
|
||||
}
|
||||
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
if (ObjectUtils.isEmpty(this.supportedClasses)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
for (Class supportedClass : this.supportedClasses) {
|
||||
if (supportedClass.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Marshalling
|
||||
|
||||
@Override
|
||||
protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
|
||||
HierarchicalStreamWriter streamWriter;
|
||||
if (node instanceof Document) {
|
||||
streamWriter = new DomWriter((Document) node);
|
||||
}
|
||||
else if (node instanceof Element) {
|
||||
streamWriter = new DomWriter((Element) node, node.getOwnerDocument(), new XmlFriendlyReplacer());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("DOMResult contains neither Document nor Element");
|
||||
}
|
||||
marshal(graph, streamWriter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException {
|
||||
ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter);
|
||||
marshalSaxHandlers(graph, contentHandler, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
|
||||
try {
|
||||
marshal(graph, new StaxWriter(new QNameMap(), streamWriter));
|
||||
}
|
||||
catch (XMLStreamException ex) {
|
||||
throw convertXStreamException(ex, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException {
|
||||
marshalWriter(graph, new OutputStreamWriter(outputStream, this.encoding));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
|
||||
throws XmlMappingException {
|
||||
|
||||
SaxWriter saxWriter = new SaxWriter();
|
||||
saxWriter.setContentHandler(contentHandler);
|
||||
marshal(graph, saxWriter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
|
||||
if (this.streamDriver != null) {
|
||||
marshal(graph, this.streamDriver.createWriter(writer));
|
||||
}
|
||||
else {
|
||||
marshal(graph, new CompactWriter(writer));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals the given graph to the given XStream HierarchicalStreamWriter.
|
||||
* Converts exceptions using {@link #convertXStreamException}.
|
||||
*/
|
||||
private void marshal(Object graph, HierarchicalStreamWriter streamWriter) {
|
||||
try {
|
||||
getXStream().marshal(graph, streamWriter);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw convertXStreamException(ex, true);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
streamWriter.flush();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.debug("Could not flush HierarchicalStreamWriter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
@Override
|
||||
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
|
||||
HierarchicalStreamReader streamReader;
|
||||
if (node instanceof Document) {
|
||||
streamReader = new DomReader((Document) node);
|
||||
}
|
||||
else if (node instanceof Element) {
|
||||
streamReader = new DomReader((Element) node);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("DOMSource contains neither Document nor Element");
|
||||
}
|
||||
return unmarshal(streamReader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException {
|
||||
try {
|
||||
XMLStreamReader streamReader = StaxUtils.createEventStreamReader(eventReader);
|
||||
return unmarshalXmlStreamReader(streamReader);
|
||||
}
|
||||
catch (XMLStreamException ex) {
|
||||
throw convertXStreamException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException {
|
||||
return unmarshal(new StaxReader(new QNameMap(), streamReader));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
|
||||
return unmarshalReader(new InputStreamReader(inputStream, this.encoding));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
|
||||
if (streamDriver != null) {
|
||||
return unmarshal(streamDriver.createReader(reader));
|
||||
}
|
||||
else {
|
||||
return unmarshal(new XppReader(reader));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
|
||||
throws XmlMappingException, IOException {
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
"XStreamMarshaller does not support unmarshalling using SAX XMLReaders");
|
||||
}
|
||||
|
||||
private Object unmarshal(HierarchicalStreamReader streamReader) {
|
||||
try {
|
||||
return this.getXStream().unmarshal(streamReader);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw convertXStreamException(ex, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given XStream exception to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> hierarchy.
|
||||
* <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
|
||||
* unmarshalling, since XStream itself does not make this distinction in its exception hierarchy.
|
||||
* @param ex XStream exception that occured
|
||||
* @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
|
||||
* or unmarshalling (<code>false</code>)
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
protected XmlMappingException convertXStreamException(Exception ex, boolean marshalling) {
|
||||
if (ex instanceof StreamException || ex instanceof CannotResolveClassException ||
|
||||
ex instanceof ConversionException) {
|
||||
if (marshalling) {
|
||||
return new MarshallingFailureException("XStream marshalling exception", ex);
|
||||
}
|
||||
else {
|
||||
return new UnmarshallingFailureException("XStream unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
return new UncategorizedMappingException("Unknown XStream exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xstream;
|
||||
|
||||
import com.thoughtworks.xstream.converters.ConversionException;
|
||||
import com.thoughtworks.xstream.io.StreamException;
|
||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||
|
||||
import org.springframework.oxm.MarshallingFailureException;
|
||||
import org.springframework.oxm.UncategorizedMappingException;
|
||||
import org.springframework.oxm.UnmarshallingFailureException;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
|
||||
/**
|
||||
* Generic utility methods for working with XStream. Mainly for internal use within the framework.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
abstract class XStreamUtils {
|
||||
|
||||
/**
|
||||
* Convert the given XStream exception to an appropriate exception from the
|
||||
* <code>org.springframework.oxm</code> hierarchy.
|
||||
* <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
|
||||
* unmarshalling, since XStream itself does not make this distinction in its exception hierarchy.
|
||||
* @param ex XStream exception that occured
|
||||
* @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
|
||||
* or unmarshalling (<code>false</code>)
|
||||
* @return the corresponding <code>XmlMappingException</code>
|
||||
*/
|
||||
public static XmlMappingException convertXStreamException(Exception ex, boolean marshalling) {
|
||||
if (ex instanceof StreamException || ex instanceof CannotResolveClassException ||
|
||||
ex instanceof ConversionException) {
|
||||
if (marshalling) {
|
||||
return new MarshallingFailureException("XStream marshalling exception", ex);
|
||||
}
|
||||
else {
|
||||
return new UnmarshallingFailureException("XStream unmarshalling exception", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
return new UncategorizedMappingException("Unknown XStream exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package providing integration of <a href="http://xstream.codehaus.org/">XStream</a> with Springs O/X Mapping support
|
||||
*
|
||||
*/
|
||||
package org.springframework.oxm.xstream;
|
||||
|
||||
1
spring-oxm/src/main/resources/META-INF/spring.handlers
Normal file
1
spring-oxm/src/main/resources/META-INF/spring.handlers
Normal file
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/oxm=org.springframework.oxm.config.OxmNamespaceHandler
|
||||
3
spring-oxm/src/main/resources/META-INF/spring.schemas
Normal file
3
spring-oxm/src/main/resources/META-INF/spring.schemas
Normal file
@@ -0,0 +1,3 @@
|
||||
http\://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd=org/springframework/oxm/config/spring-oxm-3.0.xsd
|
||||
http\://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd=org/springframework/oxm/config/spring-oxm-3.1.xsd
|
||||
http\://www.springframework.org/schema/oxm/spring-oxm.xsd=org/springframework/oxm/config/spring-oxm-3.1.xsd
|
||||
4
spring-oxm/src/main/resources/META-INF/spring.tooling
Normal file
4
spring-oxm/src/main/resources/META-INF/spring.tooling
Normal file
@@ -0,0 +1,4 @@
|
||||
# Tooling related information for the oxm namespace
|
||||
http\://www.springframework.org/schema/oxm@name=oxm Namespace
|
||||
http\://www.springframework.org/schema/oxm@prefix=oxm
|
||||
http\://www.springframework.org/schema/oxm@icon=org/springframework/oxm/config/spring-oxm.gif
|
||||
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/oxm" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/oxm" elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.0.xsd"/>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines the elements used in Spring's Object/XML Mapping integration.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="jaxb2-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.jaxb.Jaxb2Marshaller">
|
||||
Defines a JAXB2 Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.jaxb.Jaxb2Marshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="class-to-be-bound" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="name" type="classType" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="contextPath" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>The JAXB Context path</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="jibx-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.jibx.JibxMarshaller">
|
||||
Defines a JiBX Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.jibx.JibxMarshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="target-class" type="classType" use="required"/>
|
||||
<xsd:attribute name="bindingName" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>The binding name used by this marshaller.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="xmlbeans-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.xmlbeans.XmlBeansMarshaller">
|
||||
Defines a XMLBeans Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.xmlbeans.XmlBeansMarshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="options" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.apache.xmlbeans.XmlOptions">
|
||||
The bean name of the XmlOptions that is to be used for this marshaller. Typically a
|
||||
XmlOptionsFactoryBean definition.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.apache.xmlbeans.XmlOptions"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</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>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="direct">
|
||||
<tool:expected-type type="java.lang.Class"/>
|
||||
<tool:assignable-to restriction="class-only" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/oxm" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/oxm" elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines the elements used in Spring's Object/XML Mapping integration.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="jaxb2-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.jaxb.Jaxb2Marshaller">
|
||||
Defines a JAXB2 Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.jaxb.Jaxb2Marshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="class-to-be-bound" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="name" type="classType" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="contextPath" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>The JAXB Context path</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="jibx-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.jibx.JibxMarshaller">
|
||||
Defines a JiBX Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.jibx.JibxMarshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="target-class" type="classType" use="required"/>
|
||||
<xsd:attribute name="bindingName" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>The binding name used by this marshaller.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="xmlbeans-marshaller">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.oxm.xmlbeans.XmlBeansMarshaller">
|
||||
Defines a XMLBeans Marshaller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.oxm.xmlbeans.XmlBeansMarshaller"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="options" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.apache.xmlbeans.XmlOptions">
|
||||
The bean name of the XmlOptions that is to be used for this marshaller. Typically a
|
||||
XmlOptionsFactoryBean definition.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.apache.xmlbeans.XmlOptions"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</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.
|
||||
</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 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 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>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="direct">
|
||||
<tool:expected-type type="java.lang.Class"/>
|
||||
<tool:assignable-to restriction="class-only" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
</xsd:schema>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 321 B |
0
spring-oxm/src/test/castor/castorbuilder.properties
Normal file
0
spring-oxm/src/test/castor/castorbuilder.properties
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringWriter;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.stax.StAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractMarshallerTests {
|
||||
|
||||
protected Marshaller marshaller;
|
||||
|
||||
protected Object flights;
|
||||
|
||||
protected static final String EXPECTED_STRING =
|
||||
"<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
|
||||
"<tns:flight><tns:number>42</tns:number></tns:flight></tns:flights>";
|
||||
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
marshaller = createMarshaller();
|
||||
flights = createFlights();
|
||||
XMLUnit.setIgnoreWhitespace(true);
|
||||
}
|
||||
|
||||
protected abstract Marshaller createMarshaller() throws Exception;
|
||||
|
||||
protected abstract Object createFlights();
|
||||
|
||||
@Test
|
||||
public void marshalDOMResult() throws Exception {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
documentBuilderFactory.setNamespaceAware(true);
|
||||
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document result = builder.newDocument();
|
||||
DOMResult domResult = new DOMResult(result);
|
||||
marshaller.marshal(flights, domResult);
|
||||
Document expected = builder.newDocument();
|
||||
Element flightsElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:flights");
|
||||
Attr namespace = expected.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:tns");
|
||||
namespace.setNodeValue("http://samples.springframework.org/flight");
|
||||
flightsElement.setAttributeNode(namespace);
|
||||
expected.appendChild(flightsElement);
|
||||
Element flightElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:flight");
|
||||
flightsElement.appendChild(flightElement);
|
||||
Element numberElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:number");
|
||||
flightElement.appendChild(numberElement);
|
||||
Text text = expected.createTextNode("42");
|
||||
numberElement.appendChild(text);
|
||||
assertXMLEqual("Marshaller writes invalid DOMResult", expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalEmptyDOMResult() throws Exception {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
documentBuilderFactory.setNamespaceAware(true);
|
||||
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
|
||||
DOMResult domResult = new DOMResult();
|
||||
marshaller.marshal(flights, domResult);
|
||||
assertTrue("DOMResult does not contain a Document", domResult.getNode() instanceof Document);
|
||||
Document result = (Document) domResult.getNode();
|
||||
Document expected = builder.newDocument();
|
||||
Element flightsElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:flights");
|
||||
Attr namespace = expected.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:tns");
|
||||
namespace.setNodeValue("http://samples.springframework.org/flight");
|
||||
flightsElement.setAttributeNode(namespace);
|
||||
expected.appendChild(flightsElement);
|
||||
Element flightElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:flight");
|
||||
flightsElement.appendChild(flightElement);
|
||||
Element numberElement = expected.createElementNS("http://samples.springframework.org/flight", "tns:number");
|
||||
flightElement.appendChild(numberElement);
|
||||
Text text = expected.createTextNode("42");
|
||||
numberElement.appendChild(text);
|
||||
assertXMLEqual("Marshaller writes invalid DOMResult", expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStreamResultWriter() throws Exception {
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStreamResultOutputStream() throws Exception {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
StreamResult result = new StreamResult(os);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING,
|
||||
new String(os.toByteArray(), "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStaxResultStreamWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer);
|
||||
Result result = StaxUtils.createStaxResult(streamWriter);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStaxResultEventWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(writer);
|
||||
Result result = StaxUtils.createStaxResult(eventWriter);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalJaxp14StaxResultStreamWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer);
|
||||
StAXResult result = new StAXResult(streamWriter);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalJaxp14StaxResultEventWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(writer);
|
||||
StAXResult result = new StAXResult(eventWriter);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.stax.StAXSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractUnmarshallerTests {
|
||||
|
||||
protected Unmarshaller unmarshaller;
|
||||
|
||||
protected static final String INPUT_STRING =
|
||||
"<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
|
||||
"<tns:flight><tns:number>42</tns:number></tns:flight></tns:flights>";
|
||||
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
unmarshaller = createUnmarshaller();
|
||||
}
|
||||
|
||||
protected abstract Unmarshaller createUnmarshaller() throws Exception;
|
||||
|
||||
protected abstract void testFlights(Object o);
|
||||
|
||||
protected abstract void testFlight(Object o);
|
||||
|
||||
@Test
|
||||
public void unmarshalDomSource() throws Exception {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element flightsElement = document.createElementNS("http://samples.springframework.org/flight", "tns:flights");
|
||||
document.appendChild(flightsElement);
|
||||
Element flightElement = document.createElementNS("http://samples.springframework.org/flight", "tns:flight");
|
||||
flightsElement.appendChild(flightElement);
|
||||
Element numberElement = document.createElementNS("http://samples.springframework.org/flight", "tns:number");
|
||||
flightElement.appendChild(numberElement);
|
||||
Text text = document.createTextNode("42");
|
||||
numberElement.appendChild(text);
|
||||
DOMSource source = new DOMSource(document);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStreamSourceReader() throws Exception {
|
||||
StreamSource source = new StreamSource(new StringReader(INPUT_STRING));
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStreamSourceInputStream() throws Exception {
|
||||
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8")));
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalSAXSource() throws Exception {
|
||||
XMLReader reader = XMLReaderFactory.createXMLReader();
|
||||
SAXSource source = new SAXSource(reader, new InputSource(new StringReader(INPUT_STRING)));
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
Source source = StaxUtils.createStaxSource(streamReader);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStaxSourceXmlEventReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(INPUT_STRING));
|
||||
Source source = StaxUtils.createStaxSource(eventReader);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalJaxp14StaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
StAXSource source = new StAXSource(streamReader);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalJaxp14StaxSourceXmlEventReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(INPUT_STRING));
|
||||
StAXSource source = new StAXSource(eventReader);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlights(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalPartialStaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
streamReader.nextTag(); // skip to flights
|
||||
assertEquals("Invalid element", new QName("http://samples.springframework.org/flight", "flights"),
|
||||
streamReader.getName());
|
||||
streamReader.nextTag(); // skip to flight
|
||||
assertEquals("Invalid element", new QName("http://samples.springframework.org/flight", "flight"),
|
||||
streamReader.getName());
|
||||
Source source = StaxUtils.createStaxSource(streamReader);
|
||||
Object flight = unmarshaller.unmarshal(source);
|
||||
testFlight(flight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.custommonkey.xmlunit.NamespaceContext;
|
||||
import org.custommonkey.xmlunit.SimpleNamespaceContext;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.custommonkey.xmlunit.XpathEngine;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.oxm.AbstractMarshallerTests;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
import static org.easymock.EasyMock.*;
|
||||
|
||||
/**
|
||||
* Tests the {@link CastorMarshaller} class.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Jakub Narloch
|
||||
*/
|
||||
public class CastorMarshallerTests extends AbstractMarshallerTests {
|
||||
|
||||
/**
|
||||
* 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\"" +
|
||||
" 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\"" +
|
||||
" 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\"" +
|
||||
" xsi:type=\"java:org.springframework.oxm.castor.CastorObject\">" +
|
||||
"<name>test</name><value>8</value></castor-object></objects>";
|
||||
|
||||
@Override
|
||||
protected Marshaller createMarshaller() throws Exception {
|
||||
CastorMarshaller marshaller = new CastorMarshaller();
|
||||
ClassPathResource mappingLocation = new ClassPathResource("mapping.xml", CastorMarshaller.class);
|
||||
marshaller.setMappingLocation(mappingLocation);
|
||||
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 handlerMock = createMock(ContentHandler.class);
|
||||
handlerMock.startDocument();
|
||||
handlerMock.startPrefixMapping("tns", "http://samples.springframework.org/flight");
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("flights"), eq("tns:flights"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("flight"), eq("tns:flight"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("number"), eq("tns:number"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.characters(aryEq(new char[]{'4', '2'}), eq(0), eq(2));
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "number", "tns:number");
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "flight", "tns:flight");
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "flights", "tns:flights");
|
||||
handlerMock.endPrefixMapping("tns");
|
||||
handlerMock.endDocument();
|
||||
|
||||
replay(handlerMock);
|
||||
SAXResult result = new SAXResult(handlerMock);
|
||||
marshaller.marshal(flights, result);
|
||||
verify(handlerMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supports() throws Exception {
|
||||
Assert.assertTrue("CastorMarshaller does not support Flights", marshaller.supports(Flights.class));
|
||||
Assert.assertTrue("CastorMarshaller does not support Flight", marshaller.supports(Flight.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuppressNamespacesTrue() throws Exception {
|
||||
getCastorMarshaller().setSuppressNamespaces(true);
|
||||
String result = marshalFlights();
|
||||
assertXMLEqual("Marshaller wrote invalid result", SUPPRESSED_NAMESPACE_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuppressNamespacesFalse() throws Exception {
|
||||
getCastorMarshaller().setSuppressNamespaces(false);
|
||||
String result = marshalFlights();
|
||||
assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuppressXsiTypeTrue() throws Exception {
|
||||
CastorObject castorObject = createCastorObject();
|
||||
|
||||
getCastorMarshaller().setSuppressXsiType(true);
|
||||
getCastorMarshaller().setRootElement("objects");
|
||||
String result = marshal(Arrays.asList(castorObject));
|
||||
assertXMLEqual("Marshaller wrote invalid result", SUPPRESSED_XSI_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuppressXsiTypeFalse() throws Exception {
|
||||
CastorObject castorObject = createCastorObject();
|
||||
|
||||
getCastorMarshaller().setSuppressXsiType(false);
|
||||
getCastorMarshaller().setRootElement("objects");
|
||||
String result = marshal(Arrays.asList(castorObject));
|
||||
assertXMLEqual("Marshaller wrote invalid result", XSI_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarshalAsDocumentTrue() throws Exception {
|
||||
|
||||
getCastorMarshaller().setMarshalAsDocument(true);
|
||||
String result = marshalFlights();
|
||||
assertXMLEqual("Marshaller wrote invalid result", DOCUMENT_EXPECTED_STRING, result);
|
||||
Assert.assertTrue("Result doesn't contain xml declaration.",
|
||||
result.contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarshalAsDocumentFalse() throws Exception {
|
||||
|
||||
getCastorMarshaller().setMarshalAsDocument(true);
|
||||
String result = marshalFlights();
|
||||
assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result);
|
||||
Assert.assertFalse("Result contains xml declaration.", result.matches("<\\?\\s*xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRootElement() throws Exception {
|
||||
|
||||
getCastorMarshaller().setRootElement("canceledFlights");
|
||||
String result = marshalFlights();
|
||||
assertXMLEqual("Marshaller wrote invalid result", ROOT_ELEMENT_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoNamespaceSchemaLocation() throws Exception {
|
||||
String noNamespaceSchemaLocation = "flights.xsd";
|
||||
|
||||
getCastorMarshaller().setNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
|
||||
String result = marshalFlights();
|
||||
|
||||
assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.",
|
||||
noNamespaceSchemaLocation, "/tns:flights/@xsi:noNamespaceSchemaLocation", result);
|
||||
assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaLocation() throws Exception {
|
||||
String schemaLocation = "flights.xsd";
|
||||
|
||||
getCastorMarshaller().setSchemaLocation(schemaLocation);
|
||||
String result = marshalFlights();
|
||||
|
||||
assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.",
|
||||
schemaLocation, "/tns:flights/@xsi:schemaLocation", result);
|
||||
assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseXsiTypeAsRootTrue() throws Exception {
|
||||
CastorObject castorObject = createCastorObject();
|
||||
|
||||
getCastorMarshaller().setSuppressXsiType(false);
|
||||
getCastorMarshaller().setUseXSITypeAtRoot(true);
|
||||
getCastorMarshaller().setRootElement("objects");
|
||||
String result = marshal(Arrays.asList(castorObject));
|
||||
assertXMLEqual("Marshaller wrote invalid result", ROOT_WITH_XSI_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseXsiTypeAsRootFalse() throws Exception {
|
||||
CastorObject castorObject = createCastorObject();
|
||||
|
||||
getCastorMarshaller().setSuppressXsiType(false);
|
||||
getCastorMarshaller().setUseXSITypeAtRoot(false);
|
||||
getCastorMarshaller().setRootElement("objects");
|
||||
String result = marshal(Arrays.asList(castorObject));
|
||||
assertXMLEqual("Marshaller wrote invalid result", ROOT_WITHOUT_XSI_EXPECTED_STRING, result);
|
||||
}
|
||||
|
||||
|
||||
private CastorMarshaller getCastorMarshaller() {
|
||||
return (CastorMarshaller) marshaller;
|
||||
}
|
||||
|
||||
private String marshal(Object object) throws Exception {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
getCastorMarshaller().marshal(object, result);
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
private String marshalFlights() throws Exception {
|
||||
return marshal(flights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts 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<String, String>();
|
||||
namespaces.put("tns", "http://samples.springframework.org/flight");
|
||||
namespaces.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
NamespaceContext ctx = new SimpleNamespaceContext(namespaces);
|
||||
XpathEngine engine = XMLUnit.newXpathEngine();
|
||||
engine.setNamespaceContext(ctx);
|
||||
|
||||
Document doc = XMLUnit.buildControlDocument(xmlDoc);
|
||||
NodeList node = engine.getMatchingNodes(xpath, doc);
|
||||
|
||||
assertEquals(msg, expected, node.item(0).getNodeValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a instance of {@link CastorObject} for testing.
|
||||
*
|
||||
* @return a instance of {@link CastorObject}
|
||||
*/
|
||||
private CastorObject createCastorObject() {
|
||||
CastorObject castorObject = new CastorObject();
|
||||
castorObject.setName("test");
|
||||
castorObject.setValue(8);
|
||||
return castorObject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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 javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.oxm.AbstractUnmarshallerTests;
|
||||
import org.springframework.oxm.MarshallingException;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests the {@link CastorMarshaller} class.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Jakub Narloch
|
||||
*/
|
||||
public class CastorUnmarshallerTests extends AbstractUnmarshallerTests {
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
assertEquals("Number is invalid", 42L, (long) flight.getNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Unmarshaller createUnmarshaller() throws Exception {
|
||||
CastorMarshaller marshaller = new CastorMarshaller();
|
||||
ClassPathResource mappingLocation = new ClassPathResource("mapping.xml", CastorMarshaller.class);
|
||||
marshaller.setMappingLocation(mappingLocation);
|
||||
marshaller.afterPropertiesSet();
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalTargetClass() throws Exception {
|
||||
CastorMarshaller unmarshaller = new CastorMarshaller();
|
||||
unmarshaller.setTargetClasses(new Class[] { 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 testSetBothTargetClassesAndMapping() throws IOException {
|
||||
CastorMarshaller unmarshaller = new CastorMarshaller();
|
||||
unmarshaller.setMappingLocation(new ClassPathResource("order-mapping.xml", CastorMarshaller.class));
|
||||
unmarshaller.setTargetClasses(new Class[] { 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());
|
||||
assertEquals("Invalid items", 15, (int)item.getQuantity());
|
||||
item = order.getOrderItem(1);
|
||||
assertEquals("Invalid items", "3", item.getId());
|
||||
assertEquals("Invalid items", 20, (int)item.getQuantity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespacePreserveTrue() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setWhitespacePreserve(true);
|
||||
Object result = unmarshalFlights();
|
||||
testFlights(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespacePreserveFalse() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setWhitespacePreserve(false);
|
||||
Object result = unmarshalFlights();
|
||||
testFlights(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreExtraAttributesTrue() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setIgnoreExtraAttributes(true);
|
||||
Object result = unmarshal(EXTRA_ATTRIBUTES_STRING);
|
||||
testFlights(result);
|
||||
}
|
||||
|
||||
@Test(expected = MarshallingException.class)
|
||||
public void testIgnoreExtraAttributesFalse() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setIgnoreExtraAttributes(false);
|
||||
unmarshal(EXTRA_ATTRIBUTES_STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Not working yet")
|
||||
public void testIgnoreExtraElementsTrue() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setIgnoreExtraElements(true);
|
||||
getCastorUnmarshaller().setValidating(false);
|
||||
Object result = unmarshal(EXTRA_ELEMENTS_STRING);
|
||||
testFlights(result);
|
||||
}
|
||||
|
||||
@Test(expected = MarshallingException.class)
|
||||
public void testIgnoreExtraElementsFalse() throws Exception {
|
||||
|
||||
getCastorUnmarshaller().setIgnoreExtraElements(false);
|
||||
unmarshal(EXTRA_ELEMENTS_STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObject() throws Exception {
|
||||
|
||||
Flights flights = new Flights();
|
||||
getCastorUnmarshaller().setObject(flights);
|
||||
Object result = unmarshalFlights();
|
||||
|
||||
testFlights(result);
|
||||
assertSame("Result Flights is different object.", flights, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearCollectionsTrue() throws Exception {
|
||||
|
||||
Flights flights = new Flights();
|
||||
flights.setFlight(new Flight[]{new Flight()});
|
||||
getCastorUnmarshaller().setObject(flights);
|
||||
getCastorUnmarshaller().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
|
||||
@Ignore("Fails on the builder server for some reason")
|
||||
public void testClearCollectionsFalse() throws Exception {
|
||||
|
||||
Flights flights = new Flights();
|
||||
flights.setFlight(new Flight[]{new Flight(), null});
|
||||
getCastorUnmarshaller().setObject(flights);
|
||||
getCastorUnmarshaller().setClearCollections(false);
|
||||
Object result = unmarshalFlights();
|
||||
|
||||
assertSame("Result Flights is different object.", flights, result);
|
||||
assertEquals("Result Flights has incorrect number of Flight.", 3, ((Flights) result).getFlightCount());
|
||||
assertNull("Flight shouldn't have number.", flights.getFlight(0).getNumber());
|
||||
assertNull("Null Flight was expected.", flights.getFlight()[1]);
|
||||
testFlight(flights.getFlight()[2]);
|
||||
}
|
||||
|
||||
private CastorMarshaller getCastorUnmarshaller() {
|
||||
return (CastorMarshaller) unmarshaller;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.apache.xmlbeans.XmlOptions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.oxm.castor.CastorMarshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.oxm.xmlbeans.XmlBeansMarshaller;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests the {@link OxmNamespaceHandler} class.
|
||||
*
|
||||
* @author Arjen Poustma
|
||||
* @author Jakub Narloch
|
||||
*/
|
||||
public class OxmNamespaceHandlerTests {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Before
|
||||
public void createAppContext() throws Exception {
|
||||
applicationContext = new ClassPathXmlApplicationContext("oxmNamespaceHandlerTest.xml", getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlBeansMarshaller() throws Exception {
|
||||
XmlBeansMarshaller marshaller = applicationContext.getBean("xmlBeansMarshaller", XmlBeansMarshaller.class);
|
||||
XmlOptions options = marshaller.getXmlOptions();
|
||||
assertNotNull("Options not set", options);
|
||||
assertTrue("option not set", options.hasOption("SAVE_PRETTY_PRINT"));
|
||||
assertEquals("option not set", "true", options.get("SAVE_PRETTY_PRINT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jaxb2ContextPathMarshaller() throws Exception {
|
||||
Jaxb2Marshaller jaxb2Marshaller = applicationContext.getBean("jaxb2ContextPathMarshaller", Jaxb2Marshaller.class);
|
||||
assertNotNull(jaxb2Marshaller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jaxb2ClassesToBeBoundMarshaller() throws Exception {
|
||||
Jaxb2Marshaller jaxb2Marshaller = applicationContext.getBean("jaxb2ClassesMarshaller", Jaxb2Marshaller.class);
|
||||
assertNotNull(jaxb2Marshaller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void castorEncodingMarshaller() throws Exception {
|
||||
CastorMarshaller castorMarshaller = applicationContext.getBean("castorEncodingMarshaller", CastorMarshaller.class);
|
||||
assertNotNull(castorMarshaller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void castorTargetClassMarshaller() throws Exception {
|
||||
CastorMarshaller castorMarshaller = applicationContext.getBean("castorTargetClassMarshaller", CastorMarshaller.class);
|
||||
assertNotNull(castorMarshaller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void castorTargetPackageMarshaller() throws Exception {
|
||||
CastorMarshaller castorMarshaller = applicationContext.getBean("castorTargetPackageMarshaller", CastorMarshaller.class);
|
||||
assertNotNull(castorMarshaller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void castorMappingLocationMarshaller() throws Exception {
|
||||
CastorMarshaller castorMarshaller = applicationContext.getBean("castorMappingLocationMarshaller", CastorMarshaller.class);
|
||||
assertNotNull(castorMarshaller);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2007 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.jaxb;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.xml.bind.annotation.XmlAttachmentRef;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement(namespace = "http://springframework.org/spring-ws")
|
||||
public class BinaryObject {
|
||||
|
||||
@XmlElement(namespace = "http://springframework.org/spring-ws")
|
||||
private byte[] bytes;
|
||||
|
||||
@XmlElement(namespace = "http://springframework.org/spring-ws")
|
||||
private DataHandler dataHandler;
|
||||
|
||||
@XmlElement(namespace = "http://springframework.org/spring-ws")
|
||||
@XmlAttachmentRef
|
||||
private DataHandler swaDataHandler;
|
||||
|
||||
public BinaryObject() {
|
||||
}
|
||||
|
||||
public BinaryObject(byte[] bytes, DataHandler dataHandler) {
|
||||
this.bytes = bytes;
|
||||
this.dataHandler = dataHandler;
|
||||
swaDataHandler = dataHandler;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public DataHandler getDataHandler() {
|
||||
return dataHandler;
|
||||
}
|
||||
|
||||
public DataHandler getSwaDataHandler() {
|
||||
return swaDataHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jaxb;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.AbstractMarshallerTests;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.UncategorizedMappingException;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.oxm.jaxb.test.FlightType;
|
||||
import org.springframework.oxm.jaxb.test.Flights;
|
||||
import org.springframework.oxm.jaxb.test.ObjectFactory;
|
||||
import org.springframework.oxm.mime.MimeContainer;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.assertFalse;
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
import static org.custommonkey.xmlunit.XMLAssert.fail;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
|
||||
|
||||
private static final String CONTEXT_PATH = "org.springframework.oxm.jaxb.test";
|
||||
|
||||
private Jaxb2Marshaller marshaller;
|
||||
|
||||
private Flights flights;
|
||||
|
||||
@Override
|
||||
public Marshaller createMarshaller() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setContextPath(CONTEXT_PATH);
|
||||
marshaller.afterPropertiesSet();
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createFlights() {
|
||||
FlightType flight = new FlightType();
|
||||
flight.setNumber(42L);
|
||||
flights = new Flights();
|
||||
flights.getFlight().add(flight);
|
||||
return flights;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalSAXResult() throws Exception {
|
||||
ContentHandler handlerMock = createStrictMock(ContentHandler.class);
|
||||
handlerMock.setDocumentLocator(isA(Locator.class));
|
||||
handlerMock.startDocument();
|
||||
handlerMock.startPrefixMapping("", "http://samples.springframework.org/flight");
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("flights"), eq("flights"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("flight"), eq("flight"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.startElement(eq("http://samples.springframework.org/flight"), eq("number"), eq("number"),
|
||||
isA(Attributes.class));
|
||||
handlerMock.characters(isA(char[].class), eq(0), eq(2));
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "number", "number");
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "flight", "flight");
|
||||
handlerMock.endElement("http://samples.springframework.org/flight", "flights", "flights");
|
||||
handlerMock.endPrefixMapping("");
|
||||
handlerMock.endDocument();
|
||||
replay(handlerMock);
|
||||
|
||||
SAXResult result = new SAXResult(handlerMock);
|
||||
marshaller.marshal(flights, result);
|
||||
verify(handlerMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lazyInit() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setContextPath(CONTEXT_PATH);
|
||||
marshaller.setLazyInit(true);
|
||||
marshaller.afterPropertiesSet();
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
marshaller.marshal(flights, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properties() throws Exception {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setContextPath(CONTEXT_PATH);
|
||||
marshaller.setMarshallerProperties(
|
||||
Collections.<String, Object>singletonMap(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT,
|
||||
Boolean.TRUE));
|
||||
marshaller.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void noContextPathOrClassesToBeBound() throws Exception {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = UncategorizedMappingException.class)
|
||||
public void testInvalidContextPath() throws Exception {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setContextPath("ab");
|
||||
marshaller.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = XmlMappingException.class)
|
||||
public void marshalInvalidClass() throws Exception {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(FlightType.class);
|
||||
marshaller.afterPropertiesSet();
|
||||
Result result = new StreamResult(new StringWriter());
|
||||
Flights flights = new Flights();
|
||||
marshaller.marshal(flights, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsContextPath() throws Exception {
|
||||
testSupports();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsClassesToBeBound() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(Flights.class, FlightType.class);
|
||||
marshaller.afterPropertiesSet();
|
||||
testSupports();
|
||||
}
|
||||
|
||||
private void testSupports() throws Exception {
|
||||
assertTrue("Jaxb2Marshaller does not support Flights class", marshaller.supports(Flights.class));
|
||||
assertTrue("Jaxb2Marshaller does not support Flights generic type", marshaller.supports((Type)Flights.class));
|
||||
|
||||
assertFalse("Jaxb2Marshaller supports FlightType class", marshaller.supports(FlightType.class));
|
||||
assertFalse("Jaxb2Marshaller supports FlightType type", marshaller.supports((Type)FlightType.class));
|
||||
|
||||
Method method = ObjectFactory.class.getDeclaredMethod("createFlight", FlightType.class);
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement<FlightsType>",
|
||||
marshaller.supports(method.getGenericReturnType()));
|
||||
|
||||
marshaller.setSupportJaxbElementClass(true);
|
||||
JAXBElement<FlightType> flightTypeJAXBElement = new JAXBElement<FlightType>(new QName("http://springframework.org", "flight"), FlightType.class,
|
||||
new FlightType());
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement<FlightsType>", marshaller.supports(flightTypeJAXBElement.getClass()));
|
||||
|
||||
assertFalse("Jaxb2Marshaller supports class not in context path", marshaller.supports(DummyRootElement.class));
|
||||
assertFalse("Jaxb2Marshaller supports type not in context path", marshaller.supports((Type)DummyRootElement.class));
|
||||
method = getClass().getDeclaredMethod("createDummyRootElement");
|
||||
assertFalse("Jaxb2Marshaller supports JAXBElement not in context path",
|
||||
marshaller.supports(method.getGenericReturnType()));
|
||||
|
||||
assertFalse("Jaxb2Marshaller supports class not in context path", marshaller.supports(DummyType.class));
|
||||
assertFalse("Jaxb2Marshaller supports type not in context path", marshaller.supports((Type)DummyType.class));
|
||||
method = getClass().getDeclaredMethod("createDummyType");
|
||||
assertFalse("Jaxb2Marshaller supports JAXBElement not in context path",
|
||||
marshaller.supports(method.getGenericReturnType()));
|
||||
|
||||
testSupportsPrimitives();
|
||||
testSupportsStandardClasses();
|
||||
}
|
||||
|
||||
private void testSupportsPrimitives() {
|
||||
final Primitives primitives = new Primitives();
|
||||
ReflectionUtils.doWithMethods(Primitives.class, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Type returnType = method.getGenericReturnType();
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(9) + ">",
|
||||
marshaller.supports(returnType));
|
||||
try {
|
||||
// make sure the marshalling does not result in errors
|
||||
Object returnValue = method.invoke(primitives);
|
||||
marshaller.marshal(returnValue, new StreamResult(new ByteArrayOutputStream()));
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}, new ReflectionUtils.MethodFilter() {
|
||||
public boolean matches(Method method) {
|
||||
return method.getName().startsWith("primitive");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void testSupportsStandardClasses() throws Exception {
|
||||
final StandardClasses standardClasses = new StandardClasses();
|
||||
ReflectionUtils.doWithMethods(StandardClasses.class, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Type returnType = method.getGenericReturnType();
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(13) + ">",
|
||||
marshaller.supports(returnType));
|
||||
try {
|
||||
// make sure the marshalling does not result in errors
|
||||
Object returnValue = method.invoke(standardClasses);
|
||||
marshaller.marshal(returnValue, new StreamResult(new ByteArrayOutputStream()));
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}, new ReflectionUtils.MethodFilter() {
|
||||
public boolean matches(Method method) {
|
||||
return method.getName().startsWith("standardClass");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsXmlRootElement() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(DummyRootElement.class, DummyType.class);
|
||||
marshaller.afterPropertiesSet();
|
||||
assertTrue("Jaxb2Marshaller does not support XmlRootElement class", marshaller.supports(DummyRootElement.class));
|
||||
assertTrue("Jaxb2Marshaller does not support XmlRootElement generic type", marshaller.supports((Type)DummyRootElement.class));
|
||||
|
||||
assertFalse("Jaxb2Marshaller supports DummyType class", marshaller.supports(DummyType.class));
|
||||
assertFalse("Jaxb2Marshaller supports DummyType type", marshaller.supports((Type)DummyType.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void marshalAttachments() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(BinaryObject.class);
|
||||
marshaller.setMtomEnabled(true);
|
||||
marshaller.afterPropertiesSet();
|
||||
MimeContainer mimeContainer = createMock(MimeContainer.class);
|
||||
|
||||
Resource logo = new ClassPathResource("spring-ws.png", getClass());
|
||||
DataHandler dataHandler = new DataHandler(new FileDataSource(logo.getFile()));
|
||||
|
||||
expect(mimeContainer.convertToXopPackage()).andReturn(true);
|
||||
mimeContainer.addAttachment(isA(String.class), isA(DataHandler.class));
|
||||
expectLastCall().times(3);
|
||||
|
||||
replay(mimeContainer);
|
||||
byte[] bytes = FileCopyUtils.copyToByteArray(logo.getInputStream());
|
||||
BinaryObject object = new BinaryObject(bytes, dataHandler);
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(object, new StreamResult(writer), mimeContainer);
|
||||
verify(mimeContainer);
|
||||
assertTrue("No XML written", writer.toString().length() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsPackagesToScan() throws Exception {
|
||||
marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setPackagesToScan(new String[] {CONTEXT_PATH});
|
||||
marshaller.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@XmlRootElement
|
||||
public static class DummyRootElement {
|
||||
|
||||
private DummyType t = new DummyType();
|
||||
|
||||
}
|
||||
|
||||
@XmlType
|
||||
public static class DummyType {
|
||||
|
||||
private String s = "Hello";
|
||||
}
|
||||
|
||||
private JAXBElement<DummyRootElement> createDummyRootElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private JAXBElement<DummyType> createDummyType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.jaxb;
|
||||
|
||||
import java.io.StringReader;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.AbstractUnmarshallerTests;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.jaxb.test.FlightType;
|
||||
import org.springframework.oxm.jaxb.test.Flights;
|
||||
import org.springframework.oxm.mime.MimeContainer;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
public class Jaxb2UnmarshallerTests extends AbstractUnmarshallerTests {
|
||||
|
||||
private static final String INPUT_STRING = "<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
|
||||
"<tns:flight><tns:number>42</tns:number></tns:flight></tns:flights>";
|
||||
|
||||
private Jaxb2Marshaller unmarshaller;
|
||||
|
||||
@Override
|
||||
public Unmarshaller createUnmarshaller() throws Exception {
|
||||
unmarshaller = new Jaxb2Marshaller();
|
||||
unmarshaller.setContextPath("org.springframework.oxm.jaxb.test");
|
||||
unmarshaller.setSchema(new ClassPathResource("org/springframework/oxm/flight.xsd"));
|
||||
unmarshaller.afterPropertiesSet();
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalAttachments() throws Exception {
|
||||
unmarshaller = new Jaxb2Marshaller();
|
||||
unmarshaller.setClassesToBeBound(BinaryObject.class);
|
||||
unmarshaller.setMtomEnabled(true);
|
||||
unmarshaller.afterPropertiesSet();
|
||||
MimeContainer mimeContainer = createMock(MimeContainer.class);
|
||||
|
||||
Resource logo = new ClassPathResource("spring-ws.png", getClass());
|
||||
DataHandler dataHandler = new DataHandler(new FileDataSource(logo.getFile()));
|
||||
|
||||
expect(mimeContainer.isXopPackage()).andReturn(true);
|
||||
expect(mimeContainer.getAttachment(
|
||||
"<6b76528d-7a9c-4def-8e13-095ab89e9bb7@http://springframework.org/spring-ws>")).andReturn(dataHandler);
|
||||
expect(mimeContainer.getAttachment(
|
||||
"<99bd1592-0521-41a2-9688-a8bfb40192fb@http://springframework.org/spring-ws>")).andReturn(dataHandler);
|
||||
expect(mimeContainer.getAttachment("696cfb9a-4d2d-402f-bb5c-59fa69e7f0b3@spring-ws.png"))
|
||||
.andReturn(dataHandler);
|
||||
replay(mimeContainer);
|
||||
String content = "<binaryObject xmlns='http://springframework.org/spring-ws'>" + "<bytes>" +
|
||||
"<xop:Include href='cid:6b76528d-7a9c-4def-8e13-095ab89e9bb7@http://springframework.org/spring-ws' xmlns:xop='http://www.w3.org/2004/08/xop/include'/>" +
|
||||
"</bytes>" + "<dataHandler>" +
|
||||
"<xop:Include href='cid:99bd1592-0521-41a2-9688-a8bfb40192fb@http://springframework.org/spring-ws' xmlns:xop='http://www.w3.org/2004/08/xop/include'/>" +
|
||||
"</dataHandler>" +
|
||||
"<swaDataHandler>696cfb9a-4d2d-402f-bb5c-59fa69e7f0b3@spring-ws.png</swaDataHandler>" +
|
||||
"</binaryObject>";
|
||||
|
||||
StringReader reader = new StringReader(content);
|
||||
Object result = unmarshaller.unmarshal(new StreamSource(reader), mimeContainer);
|
||||
assertTrue("Result is not a BinaryObject", result instanceof BinaryObject);
|
||||
verify(mimeContainer);
|
||||
BinaryObject object = (BinaryObject) result;
|
||||
assertNotNull("bytes property not set", object.getBytes());
|
||||
assertTrue("bytes property not set", object.getBytes().length > 0);
|
||||
assertNotNull("datahandler property not set", object.getSwaDataHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlights(Object o) {
|
||||
Flights flights = (Flights) o;
|
||||
assertNotNull("Flights is null", flights);
|
||||
assertEquals("Invalid amount of flight elements", 1, flights.getFlight().size());
|
||||
testFlight(flights.getFlight().get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlight(Object o) {
|
||||
FlightType flight = (FlightType) o;
|
||||
assertNotNull("Flight is null", flight);
|
||||
assertEquals("Number is invalid", 42L, flight.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void unmarshalPartialStaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
streamReader.nextTag(); // skip to flights
|
||||
streamReader.nextTag(); // skip to flight
|
||||
Source source = StaxUtils.createStaxSource(streamReader);
|
||||
JAXBElement<FlightType> element = (JAXBElement<FlightType>) unmarshaller.unmarshal(source);
|
||||
FlightType flight = element.getValue();
|
||||
testFlight(flight);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.jaxb;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
* Used by {@link org.springframework.oxm.jaxb.Jaxb2MarshallerTests}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class Primitives {
|
||||
|
||||
private static final QName NAME = new QName("http://springframework.org/oxm-test", "primitives");
|
||||
|
||||
// following methods are used to test support for primitives
|
||||
public JAXBElement<Boolean> primitiveBoolean() {
|
||||
return new JAXBElement<Boolean>(NAME, Boolean.class, true);
|
||||
}
|
||||
|
||||
public JAXBElement<Byte> primitiveByte() {
|
||||
return new JAXBElement<Byte>(NAME, Byte.class, (byte)42);
|
||||
}
|
||||
|
||||
public JAXBElement<Short> primitiveShort() {
|
||||
return new JAXBElement<Short>(NAME, Short.class, (short)42);
|
||||
}
|
||||
|
||||
public JAXBElement<Integer> primitiveInteger() {
|
||||
return new JAXBElement<Integer>(NAME, Integer.class, 42);
|
||||
}
|
||||
|
||||
public JAXBElement<Long> primitiveLong() {
|
||||
return new JAXBElement<Long>(NAME, Long.class, 42L);
|
||||
}
|
||||
|
||||
public JAXBElement<Double> primitiveDouble() {
|
||||
return new JAXBElement<Double>(NAME, Double.class, 42D);
|
||||
}
|
||||
|
||||
public JAXBElement<byte[]> primitiveByteArray() {
|
||||
return new JAXBElement<byte[]>(NAME, byte[].class, new byte[]{42});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.jaxb;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.UUID;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.URLDataSource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
import javax.xml.datatype.DatatypeFactory;
|
||||
import javax.xml.datatype.Duration;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
* Used by {@link org.springframework.oxm.jaxb.Jaxb2MarshallerTests}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class StandardClasses {
|
||||
|
||||
private static final QName NAME = new QName("http://springframework.org/oxm-test", "standard-classes");
|
||||
|
||||
private DatatypeFactory factory;
|
||||
|
||||
public StandardClasses() throws DatatypeConfigurationException {
|
||||
factory = DatatypeFactory.newInstance();
|
||||
}
|
||||
|
||||
/*
|
||||
java.net.URI
|
||||
javax.xml.datatype.XMLGregorianCalendarxs:anySimpleType
|
||||
javax.xml.datatype.Duration
|
||||
java.lang.Object
|
||||
java.awt.Image
|
||||
javax.activation.DataHandler
|
||||
javax.xml.transform.Source
|
||||
java.util.UUID
|
||||
*/
|
||||
public JAXBElement<String> standardClassString() {
|
||||
return new JAXBElement<String>(NAME, String.class, "42");
|
||||
}
|
||||
|
||||
public JAXBElement<BigInteger> standardClassBigInteger() {
|
||||
return new JAXBElement<BigInteger>(NAME, BigInteger.class, new BigInteger("42"));
|
||||
}
|
||||
|
||||
public JAXBElement<BigDecimal> standardClassBigDecimal() {
|
||||
return new JAXBElement<BigDecimal>(NAME, BigDecimal.class, new BigDecimal("42.0"));
|
||||
}
|
||||
|
||||
public JAXBElement<Calendar> standardClassCalendar() {
|
||||
return new JAXBElement<Calendar>(NAME, Calendar.class, Calendar.getInstance());
|
||||
}
|
||||
|
||||
public JAXBElement<GregorianCalendar> standardClassGregorianCalendar() {
|
||||
return new JAXBElement<GregorianCalendar>(NAME, GregorianCalendar.class, (GregorianCalendar)Calendar.getInstance());
|
||||
}
|
||||
|
||||
public JAXBElement<Date> standardClassDate() {
|
||||
return new JAXBElement<Date>(NAME, Date.class, new Date());
|
||||
}
|
||||
|
||||
public JAXBElement<QName> standardClassQName() {
|
||||
return new JAXBElement<QName>(NAME, QName.class, NAME);
|
||||
}
|
||||
|
||||
public JAXBElement<URI> standardClassURI() {
|
||||
return new JAXBElement<URI>(NAME, URI.class, URI.create("http://springframework.org"));
|
||||
}
|
||||
|
||||
public JAXBElement<XMLGregorianCalendar> standardClassXMLGregorianCalendar() throws DatatypeConfigurationException {
|
||||
XMLGregorianCalendar calendar =
|
||||
factory.newXMLGregorianCalendar((GregorianCalendar) Calendar.getInstance());
|
||||
return new JAXBElement<XMLGregorianCalendar>(NAME, XMLGregorianCalendar.class, calendar);
|
||||
}
|
||||
|
||||
public JAXBElement<Duration> standardClassDuration() {
|
||||
Duration duration = factory.newDuration(42000);
|
||||
return new JAXBElement<Duration>(NAME, Duration.class, duration);
|
||||
}
|
||||
|
||||
public JAXBElement<Image> standardClassImage() throws IOException {
|
||||
Image image = ImageIO.read(getClass().getResourceAsStream("spring-ws.png"));
|
||||
return new JAXBElement<Image>(NAME, Image.class, image);
|
||||
}
|
||||
|
||||
public JAXBElement<DataHandler> standardClassDataHandler() {
|
||||
DataSource dataSource = new URLDataSource(getClass().getResource("spring-ws.png"));
|
||||
DataHandler dataHandler = new DataHandler(dataSource);
|
||||
return new JAXBElement<DataHandler>(NAME, DataHandler.class, dataHandler);
|
||||
}
|
||||
|
||||
/* The following should work according to the spec, but doesn't on the JAXB2 implementation including in JDK 1.6.0_17
|
||||
public JAXBElement<Source> standardClassSource() {
|
||||
StringReader reader = new StringReader("<foo/>");
|
||||
return new JAXBElement<Source>(NAME, Source.class, new StreamSource(reader));
|
||||
}
|
||||
*/
|
||||
|
||||
public JAXBElement<UUID> standardClassUUID() {
|
||||
return new JAXBElement<UUID>(NAME, UUID.class, UUID.randomUUID());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2006 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.jibx;
|
||||
|
||||
public class FlightType {
|
||||
|
||||
protected long number;
|
||||
|
||||
public long getNumber() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public void setNumber(long number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2006 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.jibx;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Flights {
|
||||
|
||||
protected ArrayList flightList = new ArrayList();
|
||||
|
||||
public void addFlight(FlightType flight) {
|
||||
flightList.add(flight);
|
||||
}
|
||||
|
||||
public FlightType getFlight(int index) {
|
||||
return (FlightType) flightList.get(index);
|
||||
}
|
||||
|
||||
public int sizeFlightList() {
|
||||
return flightList.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.jibx;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.oxm.AbstractMarshallerTests;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*
|
||||
* NOTE: These tests fail under Eclipse/IDEA because JiBX binding does
|
||||
* not occur by default. The Gradle build should succeed, however.
|
||||
*/
|
||||
public class JibxMarshallerTests extends AbstractMarshallerTests {
|
||||
|
||||
@Override
|
||||
protected Marshaller createMarshaller() throws Exception {
|
||||
JibxMarshaller marshaller = new JibxMarshaller();
|
||||
marshaller.setTargetPackage("org.springframework.oxm.jibx");
|
||||
marshaller.afterPropertiesSet();
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createFlights() {
|
||||
Flights flights = new Flights();
|
||||
FlightType flight = new FlightType();
|
||||
flight.setNumber(42L);
|
||||
flights.addFlight(flight);
|
||||
return flights;
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void afterPropertiesSetNoContextPath() throws Exception {
|
||||
JibxMarshaller marshaller = new JibxMarshaller();
|
||||
marshaller.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indentation() throws Exception {
|
||||
((JibxMarshaller) marshaller).setIndent(4);
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(flights, new StreamResult(writer));
|
||||
XMLUnit.setIgnoreWhitespace(false);
|
||||
String expected =
|
||||
"<?xml version=\"1.0\"?>\n" + "<flights xmlns=\"http://samples.springframework.org/flight\">\n" +
|
||||
" <flight>\n" + " <number>42</number>\n" + " </flight>\n" + "</flights>";
|
||||
assertXMLEqual(expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingAndStandalone() throws Exception {
|
||||
((JibxMarshaller) marshaller).setEncoding("ISO-8859-1");
|
||||
((JibxMarshaller) marshaller).setStandalone(Boolean.TRUE);
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(flights, new StreamResult(writer));
|
||||
assertTrue("Encoding and standalone not set",
|
||||
writer.toString().startsWith("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"yes\"?>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dtd() throws Exception {
|
||||
((JibxMarshaller) marshaller).setDocTypeRootElementName("flights");
|
||||
((JibxMarshaller) marshaller).setDocTypeSystemId("flights.dtd");
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(flights, new StreamResult(writer));
|
||||
assertTrue("doc type not written",
|
||||
writer.toString().contains("<!DOCTYPE flights SYSTEM \"flights.dtd\">"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupports() throws Exception {
|
||||
assertTrue("JibxMarshaller does not support Flights", marshaller.supports(Flights.class));
|
||||
assertTrue("JibxMarshaller does not support FlightType", marshaller.supports(FlightType.class));
|
||||
assertFalse("JibxMarshaller supports illegal type", marshaller.supports(getClass()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.jibx;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import org.springframework.oxm.AbstractUnmarshallerTests;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*
|
||||
* NOTE: These tests fail under Eclipse/IDEA because JiBX binding does
|
||||
* not occur by default. The Gradle build should succeed, however.
|
||||
*/
|
||||
public class JibxUnmarshallerTests extends AbstractUnmarshallerTests {
|
||||
|
||||
@Override
|
||||
protected Unmarshaller createUnmarshaller() throws Exception {
|
||||
JibxMarshaller unmarshaller = new JibxMarshaller();
|
||||
unmarshaller.setTargetClass(Flights.class);
|
||||
unmarshaller.afterPropertiesSet();
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlights(Object o) {
|
||||
Flights flights = (Flights) o;
|
||||
assertNotNull("Flights is null", flights);
|
||||
assertEquals("Invalid amount of flight elements", 1, flights.sizeFlightList());
|
||||
testFlight(flights.getFlight(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlight(Object o) {
|
||||
FlightType flight = (FlightType) o;
|
||||
assertNotNull("Flight is null", flight);
|
||||
assertEquals("Number is invalid", 42L, flight.getNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Ignore
|
||||
public void unmarshalPartialStaxSourceXmlStreamReader() throws Exception {
|
||||
// JiBX does not support reading XML fragments, hence the override here
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xmlbeans;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.oxm.AbstractMarshallerTests;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.samples.flight.FlightType;
|
||||
import org.springframework.samples.flight.FlightsDocument;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class XmlBeansMarshallerTests extends AbstractMarshallerTests {
|
||||
|
||||
@Override
|
||||
protected Marshaller createMarshaller() throws Exception {
|
||||
return new XmlBeansMarshaller();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createFlights() {
|
||||
FlightsDocument flightsDocument = FlightsDocument.Factory.newInstance();
|
||||
FlightsDocument.Flights flights = flightsDocument.addNewFlights();
|
||||
FlightType flightType = flights.addNewFlight();
|
||||
flightType.setNumber(42L);
|
||||
return flightsDocument;
|
||||
}
|
||||
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void testMarshalNonXmlObject() throws Exception {
|
||||
marshaller.marshal(new Object(), new StreamResult(new ByteArrayOutputStream()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supports() throws Exception {
|
||||
assertTrue("XmlBeansMarshaller does not support XmlObject", marshaller.supports(XmlObject.class));
|
||||
assertFalse("XmlBeansMarshaller supports other objects", marshaller.supports(Object.class));
|
||||
assertTrue("XmlBeansMarshaller does not support FlightsDocument", marshaller.supports(FlightsDocument.class));
|
||||
assertTrue("XmlBeansMarshaller does not support Flights", marshaller.supports(FlightsDocument.Flights.class));
|
||||
assertTrue("XmlBeansMarshaller does not support FlightType", marshaller.supports(FlightType.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xmlbeans;
|
||||
|
||||
import java.io.StringReader;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.oxm.AbstractUnmarshallerTests;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.ValidationFailureException;
|
||||
import org.springframework.samples.flight.FlightDocument;
|
||||
import org.springframework.samples.flight.FlightType;
|
||||
import org.springframework.samples.flight.FlightsDocument;
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class XmlBeansUnmarshallerTests extends AbstractUnmarshallerTests {
|
||||
|
||||
@Override
|
||||
protected Unmarshaller createUnmarshaller() throws Exception {
|
||||
return new XmlBeansMarshaller();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlights(Object o) {
|
||||
FlightsDocument flightsDocument = (FlightsDocument) o;
|
||||
assertNotNull("FlightsDocument is null", flightsDocument);
|
||||
FlightsDocument.Flights flights = flightsDocument.getFlights();
|
||||
assertEquals("Invalid amount of flight elements", 1, flights.sizeOfFlightArray());
|
||||
testFlight(flights.getFlightArray(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testFlight(Object o) {
|
||||
FlightType flight = null;
|
||||
if (o instanceof FlightType) {
|
||||
flight = (FlightType) o;
|
||||
}
|
||||
else if (o instanceof FlightDocument) {
|
||||
FlightDocument flightDocument = (FlightDocument) o;
|
||||
flight = flightDocument.getFlight();
|
||||
}
|
||||
assertNotNull("Flight is null", flight);
|
||||
assertEquals("Number is invalid", 42L, flight.getNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmarshalPartialStaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
streamReader.nextTag(); // skip to flights
|
||||
assertEquals("Invalid element", new QName("http://samples.springframework.org/flight", "flights"),
|
||||
streamReader.getName());
|
||||
streamReader.nextTag(); // skip to flight
|
||||
assertEquals("Invalid element", new QName("http://samples.springframework.org/flight", "flight"),
|
||||
streamReader.getName());
|
||||
Source source = StaxUtils.createStaxSource(streamReader);
|
||||
Object flight = unmarshaller.unmarshal(source);
|
||||
testFlight(flight);
|
||||
}
|
||||
|
||||
@Test(expected = ValidationFailureException.class)
|
||||
public void testValidate() throws Exception {
|
||||
((XmlBeansMarshaller) unmarshaller).setValidating(true);
|
||||
String invalidInput = "<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" +
|
||||
"<tns:flight><tns:number>abc</tns:number></tns:flight></tns:flights>";
|
||||
unmarshaller.unmarshal(new StreamSource(new StringReader(invalidInput)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xmlbeans;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class XmlOptionsFactoryBeanTests {
|
||||
|
||||
private XmlOptionsFactoryBean factoryBean = new XmlOptionsFactoryBean();
|
||||
|
||||
@Test
|
||||
public void xmlOptionsFactoryBean() throws Exception {
|
||||
factoryBean.setOptions(Collections.singletonMap(XmlOptions.SAVE_PRETTY_PRINT, Boolean.TRUE));
|
||||
XmlOptions xmlOptions = factoryBean.getObject();
|
||||
assertNotNull("No XmlOptions returned", xmlOptions);
|
||||
assertTrue("Option not set", xmlOptions.hasOption(XmlOptions.SAVE_PRETTY_PRINT));
|
||||
assertFalse("Invalid option set", xmlOptions.hasOption(XmlOptions.LOAD_LINE_NUMBERS));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2007 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.xstream;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
@XStreamAlias("flight")
|
||||
public class Flight {
|
||||
|
||||
@XStreamAlias("number")
|
||||
private long flightNumber;
|
||||
|
||||
public long getFlightNumber() {
|
||||
return flightNumber;
|
||||
}
|
||||
|
||||
public void setFlightNumber(long number) {
|
||||
this.flightNumber = number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.xstream;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class FlightSubclass extends Flight {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.springframework.oxm.xstream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Flights {
|
||||
|
||||
private List<Flight> flights = new ArrayList<Flight>();
|
||||
|
||||
private List<String> strings = new ArrayList<String>();
|
||||
|
||||
public List<Flight> getFlights() {
|
||||
return flights;
|
||||
}
|
||||
|
||||
public void setFlights(List<Flight> flights) {
|
||||
this.flights = flights;
|
||||
}
|
||||
|
||||
public List<String> getStrings() {
|
||||
return strings;
|
||||
}
|
||||
|
||||
public void setStrings(List<String> strings) {
|
||||
this.strings = strings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.xstream;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import com.thoughtworks.xstream.converters.Converter;
|
||||
import com.thoughtworks.xstream.converters.extended.EncodedByteArrayConverter;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class XStreamMarshallerTests {
|
||||
|
||||
private static final String EXPECTED_STRING = "<flight><flightNumber>42</flightNumber></flight>";
|
||||
|
||||
private XStreamMarshaller marshaller;
|
||||
|
||||
private Flight flight;
|
||||
|
||||
@Before
|
||||
public void createMarshaller() throws Exception {
|
||||
marshaller = new XStreamMarshaller();
|
||||
Map<String, String> aliases = new HashMap<String, String>();
|
||||
aliases.put("flight", Flight.class.getName());
|
||||
marshaller.setAliases(aliases);
|
||||
flight = new Flight();
|
||||
flight.setFlightNumber(42L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalDOMResult() throws Exception {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
DOMResult domResult = new DOMResult(document);
|
||||
marshaller.marshal(flight, domResult);
|
||||
Document expected = builder.newDocument();
|
||||
Element flightElement = expected.createElement("flight");
|
||||
expected.appendChild(flightElement);
|
||||
Element numberElement = expected.createElement("flightNumber");
|
||||
flightElement.appendChild(numberElement);
|
||||
Text text = expected.createTextNode("42");
|
||||
numberElement.appendChild(text);
|
||||
assertXMLEqual("Marshaller writes invalid DOMResult", expected, document);
|
||||
}
|
||||
|
||||
// see SWS-392
|
||||
@Test
|
||||
public void marshalDOMResultToExistentDocument() throws Exception {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document existent = builder.newDocument();
|
||||
Element rootElement = existent.createElement("root");
|
||||
Element flightsElement = existent.createElement("flights");
|
||||
rootElement.appendChild(flightsElement);
|
||||
existent.appendChild(rootElement);
|
||||
|
||||
// marshall into the existent document
|
||||
DOMResult domResult = new DOMResult(flightsElement);
|
||||
marshaller.marshal(flight, domResult);
|
||||
|
||||
Document expected = builder.newDocument();
|
||||
Element eRootElement = expected.createElement("root");
|
||||
Element eFlightsElement = expected.createElement("flights");
|
||||
Element eFlightElement = expected.createElement("flight");
|
||||
eRootElement.appendChild(eFlightsElement);
|
||||
eFlightsElement.appendChild(eFlightElement);
|
||||
expected.appendChild(eRootElement);
|
||||
Element eNumberElement = expected.createElement("flightNumber");
|
||||
eFlightElement.appendChild(eNumberElement);
|
||||
Text text = expected.createTextNode("42");
|
||||
eNumberElement.appendChild(text);
|
||||
assertXMLEqual("Marshaller writes invalid DOMResult", expected, existent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStreamResultWriter() throws Exception {
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
marshaller.marshal(flight, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStreamResultOutputStream() throws Exception {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
StreamResult result = new StreamResult(os);
|
||||
marshaller.marshal(flight, result);
|
||||
String s = new String(os.toByteArray(), "UTF-8");
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalSaxResult() throws Exception {
|
||||
ContentHandler handlerMock = createStrictMock(ContentHandler.class);
|
||||
handlerMock.startDocument();
|
||||
handlerMock.startElement(eq(""), eq("flight"), eq("flight"), isA(Attributes.class));
|
||||
handlerMock.startElement(eq(""), eq("flightNumber"), eq("flightNumber"), isA(Attributes.class));
|
||||
handlerMock.characters(isA(char[].class), eq(0), eq(2));
|
||||
handlerMock.endElement("", "flightNumber", "flightNumber");
|
||||
handlerMock.endElement("", "flight", "flight");
|
||||
handlerMock.endDocument();
|
||||
|
||||
replay(handlerMock);
|
||||
SAXResult result = new SAXResult(handlerMock);
|
||||
marshaller.marshal(flight, result);
|
||||
verify(handlerMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStaxResultXMLStreamWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer);
|
||||
Result result = StaxUtils.createStaxResult(streamWriter);
|
||||
marshaller.marshal(flight, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marshalStaxResultXMLEventWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(writer);
|
||||
Result result = StaxUtils.createStaxResult(eventWriter);
|
||||
marshaller.marshal(flight, result);
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converters() throws Exception {
|
||||
marshaller.setConverters(new Converter[]{new EncodedByteArrayConverter()});
|
||||
byte[] buf = new byte[]{0x1, 0x2};
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(buf, new StreamResult(writer));
|
||||
assertXMLEqual("<byte-array>AQI=</byte-array>", writer.toString());
|
||||
Reader reader = new StringReader(writer.toString());
|
||||
byte[] bufResult = (byte[]) marshaller.unmarshal(new StreamSource(reader));
|
||||
assertTrue("Invalid result", Arrays.equals(buf, bufResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useAttributesFor() throws Exception {
|
||||
marshaller.setUseAttributeForTypes(new Class[]{Long.TYPE});
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
String expected = "<flight flightNumber=\"42\" />";
|
||||
assertXMLEqual("Marshaller does not use attributes", expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useAttributesForStringClassMap() throws Exception {
|
||||
marshaller.setUseAttributeFor(Collections.singletonMap("flightNumber", Long.TYPE));
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
String expected = "<flight flightNumber=\"42\" />";
|
||||
assertXMLEqual("Marshaller does not use attributes", expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useAttributesForClassStringMap() throws Exception {
|
||||
marshaller.setUseAttributeFor(Collections.singletonMap(Flight.class, "flightNumber"));
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
String expected = "<flight flightNumber=\"42\" />";
|
||||
assertXMLEqual("Marshaller does not use attributes", expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useAttributesForClassStringListMap() throws Exception {
|
||||
marshaller
|
||||
.setUseAttributeFor(Collections.singletonMap(Flight.class, Collections.singletonList("flightNumber")));
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
String expected = "<flight flightNumber=\"42\" />";
|
||||
assertXMLEqual("Marshaller does not use attributes", expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aliasesByTypeStringClassMap() throws Exception {
|
||||
Map<String, Class<?>> aliases = new HashMap<String, Class<?>>();
|
||||
aliases.put("flight", Flight.class);
|
||||
FlightSubclass flight = new FlightSubclass();
|
||||
flight.setFlightNumber(42);
|
||||
marshaller.setAliasesByType(aliases);
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
assertXMLEqual("Marshaller does not use attributes", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aliasesByTypeStringStringMap() throws Exception {
|
||||
Map<String, String> aliases = new HashMap<String, String>();
|
||||
aliases.put("flight", Flight.class.getName());
|
||||
FlightSubclass flight = new FlightSubclass();
|
||||
flight.setFlightNumber(42);
|
||||
marshaller.setAliasesByType(aliases);
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
assertXMLEqual("Marshaller does not use attributes", EXPECTED_STRING, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldAliases() throws Exception {
|
||||
marshaller.setFieldAliases(Collections.singletonMap("org.springframework.oxm.xstream.Flight.flightNumber", "flightNo"));
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
String expected = "<flight><flightNo>42</flightNo></flight>";
|
||||
assertXMLEqual("Marshaller does not use aliases", expected, writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void omitFields() throws Exception {
|
||||
Map omittedFieldsMap = Collections.singletonMap(Flight.class, "flightNumber");
|
||||
marshaller.setOmittedFields(omittedFieldsMap);
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
assertXpathNotExists("/flight/flightNumber", writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void implicitCollections() throws Exception {
|
||||
Flights flights = new Flights();
|
||||
flights.getFlights().add(flight);
|
||||
flights.getStrings().add("42");
|
||||
|
||||
Map<String, Class> aliases = new HashMap<String, Class>();
|
||||
aliases.put("flight", Flight.class);
|
||||
aliases.put("flights", Flights.class);
|
||||
marshaller.setAliases(aliases);
|
||||
|
||||
Map implicitCollections = Collections.singletonMap(Flights.class, "flights,strings");
|
||||
marshaller.setImplicitCollections(implicitCollections);
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flights, new StreamResult(writer));
|
||||
String result = writer.toString();
|
||||
assertXpathNotExists("/flights/flights", result);
|
||||
assertXpathExists("/flights/flight", result);
|
||||
assertXpathNotExists("/flights/strings", result);
|
||||
assertXpathExists("/flights/string", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jettisonDriver() throws Exception {
|
||||
marshaller.setStreamDriver(new JettisonMappedXmlDriver());
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
assertEquals("Invalid result", "{\"flight\":{\"flightNumber\":42}}", writer.toString());
|
||||
Object o = marshaller.unmarshal(new StreamSource(new StringReader(writer.toString())));
|
||||
assertTrue("Unmarshalled object is not Flights", o instanceof Flight);
|
||||
Flight unflight = (Flight) o;
|
||||
assertNotNull("Flight is null", unflight);
|
||||
assertEquals("Number is invalid", 42L, unflight.getFlightNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonDriver() throws Exception {
|
||||
marshaller.setStreamDriver(new JsonHierarchicalStreamDriver() {
|
||||
@Override
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, new char[0], "", JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
marshaller.marshal(flight, new StreamResult(writer));
|
||||
assertEquals("Invalid result", "{\"flightNumber\": 42}", writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedMarshalStreamResultWriter() throws Exception {
|
||||
marshaller.setAnnotatedClass(Flight.class);
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
Flight flight = new Flight();
|
||||
flight.setFlightNumber(42);
|
||||
marshaller.marshal(flight, result);
|
||||
String expected = "<flight><number>42</number></flight>";
|
||||
assertXMLEqual("Marshaller writes invalid StreamResult", expected, writer.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.xstream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.util.xml.StaxUtils;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class XStreamUnmarshallerTests {
|
||||
|
||||
protected static final String INPUT_STRING = "<flight><flightNumber>42</flightNumber></flight>";
|
||||
|
||||
private XStreamMarshaller unmarshaller;
|
||||
|
||||
@Before
|
||||
public void creteUnmarshaller() throws Exception {
|
||||
unmarshaller = new XStreamMarshaller();
|
||||
Map<String, Class> aliases = new HashMap<String, Class>();
|
||||
aliases.put("flight", Flight.class);
|
||||
unmarshaller.setAliases(aliases);
|
||||
}
|
||||
|
||||
private void testFlight(Object o) {
|
||||
assertTrue("Unmarshalled object is not Flights", o instanceof Flight);
|
||||
Flight flight = (Flight) o;
|
||||
assertNotNull("Flight is null", flight);
|
||||
assertEquals("Number is invalid", 42L, flight.getFlightNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalDomSource() throws Exception {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.parse(new InputSource(new StringReader(INPUT_STRING)));
|
||||
DOMSource source = new DOMSource(document);
|
||||
Object flight = unmarshaller.unmarshal(source);
|
||||
testFlight(flight);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStaxSourceXmlStreamReader() throws Exception {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(INPUT_STRING));
|
||||
Source source = StaxUtils.createStaxSource(streamReader);
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlight(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStreamSourceInputStream() throws Exception {
|
||||
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8")));
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlight(flights);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unmarshalStreamSourceReader() throws Exception {
|
||||
StreamSource source = new StreamSource(new StringReader(INPUT_STRING));
|
||||
Object flights = unmarshaller.unmarshal(source);
|
||||
testFlight(flights);
|
||||
}
|
||||
}
|
||||
|
||||
6
spring-oxm/src/test/resources/log4j.properties
Normal file
6
spring-oxm/src/test/resources/log4j.properties
Normal file
@@ -0,0 +1,6 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
log4j.logger.org.springframework.oxm=DEBUG
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
@@ -0,0 +1,31 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">
|
||||
|
||||
<!-- XMLBeans -->
|
||||
<oxm:xmlbeans-marshaller id="xmlBeansMarshaller"
|
||||
options="xmlBeansOptions" />
|
||||
|
||||
<bean id="xmlBeansOptions" class="org.springframework.oxm.xmlbeans.XmlOptionsFactoryBean">
|
||||
<property name="options">
|
||||
<props>
|
||||
<prop key="SAVE_PRETTY_PRINT">true</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- JAXB2 -->
|
||||
<oxm:jaxb2-marshaller id="jaxb2ContextPathMarshaller"
|
||||
contextPath="org.springframework.oxm.jaxb.test" />
|
||||
|
||||
<oxm:jaxb2-marshaller id="jaxb2ClassesMarshaller">
|
||||
<oxm:class-to-be-bound name="org.springframework.oxm.jaxb.test.Flights" />
|
||||
<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>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://samples.springframework.org/flight"
|
||||
xmlns:tns="http://samples.springframework.org/flight">
|
||||
<element name="flights">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name="flight" type="tns:flightType"
|
||||
maxOccurs="unbounded">
|
||||
</element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name="flight" type="tns:flightType"/>
|
||||
<complexType name="flightType">
|
||||
<sequence>
|
||||
<element name="number" type="long"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</schema>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding>
|
||||
<mapping name="flights" class="org.springframework.oxm.jibx.Flights">
|
||||
<namespace uri="http://samples.springframework.org/flight" default="elements"/>
|
||||
<collection field="flightList">
|
||||
<structure map-as="org.springframework.oxm.jibx.FlightType"/>
|
||||
</collection>
|
||||
</mapping>
|
||||
<mapping name="flight" class="org.springframework.oxm.jibx.FlightType">
|
||||
<namespace uri="http://samples.springframework.org/flight" default="elements"/>
|
||||
<value name="number" field="number" usage="required"/>
|
||||
</mapping>
|
||||
</binding>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://samples.springframework.org/order"
|
||||
xmlns:tns="http://samples.springframework.org/order">
|
||||
<element name="order">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name="order-item" type="tns:orderItemType"
|
||||
maxOccurs="unbounded">
|
||||
</element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<complexType name="orderItemType">
|
||||
<attribute name="id" type="string" />
|
||||
<attribute name="quantity" type="int" />
|
||||
</complexType>
|
||||
</schema>
|
||||
Reference in New Issue
Block a user