
org.eclipse.persistence.internal.oxm.XMLMarshaller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 346465e
/*******************************************************************************
* Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Blaise Doughan - 2.5 - initial implementation
******************************************************************************/
package org.eclipse.persistence.internal.oxm;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import javax.xml.namespace.QName;
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.validation.Schema;
import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.AbstractMarshalRecord;
import org.eclipse.persistence.internal.oxm.record.ExtendedResult;
import org.eclipse.persistence.internal.oxm.record.namespaces.PrefixMapperNamespaceResolver;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.oxm.JSONWithPadding;
import org.eclipse.persistence.oxm.attachment.XMLAttachmentMarshaller;
import org.eclipse.persistence.oxm.record.ContentHandlerRecord;
import org.eclipse.persistence.oxm.record.FormattedOutputStreamRecord;
import org.eclipse.persistence.oxm.record.FormattedWriterRecord;
import org.eclipse.persistence.oxm.record.JSONFormattedWriterRecord;
import org.eclipse.persistence.oxm.record.JSONWriterRecord;
import org.eclipse.persistence.oxm.record.MarshalRecord;
import org.eclipse.persistence.oxm.record.NodeRecord;
import org.eclipse.persistence.oxm.record.OutputStreamRecord;
import org.eclipse.persistence.oxm.record.ValidatingMarshalRecord;
import org.eclipse.persistence.oxm.record.WriterRecord;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.platform.xml.XMLPlatform;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.ext.LexicalHandler;
public abstract class XMLMarshaller<
ABSTRACT_SESSION extends CoreAbstractSession,
CHARACTER_ESCAPE_HANDLER extends CharacterEscapeHandler,
CONTEXT extends Context,
DESCRIPTOR extends Descriptor, ?, ?, ?, ?, ?, ?, ?, ?, ?>,
MARSHALLER_LISTENER extends Marshaller.Listener,
MEDIA_TYPE extends MediaType,
NAMESPACE_PREFIX_MAPPER extends NamespacePrefixMapper,
OBJECT_BUILDER extends ObjectBuilder, ABSTRACT_SESSION, ?, XMLMarshaller>,
SESSION extends CoreSession> extends Marshaller {
protected final static String DEFAULT_XML_VERSION = "1.0";
private static final String STAX_RESULT_CLASS_NAME = "javax.xml.transform.stax.StAXResult";
private static final String GET_XML_STREAM_WRITER_METHOD_NAME = "getXMLStreamWriter";
private static final String GET_XML_EVENT_WRITER_METHOD_NAME = "getXMLEventWriter";
private static final String XML_STREAM_WRITER_RECORD_CLASS_NAME = "org.eclipse.persistence.oxm.record.XMLStreamWriterRecord";
private static final String XML_EVENT_WRITER_RECORD_CLASS_NAME = "org.eclipse.persistence.oxm.record.XMLEventWriterRecord";
private static final String XML_STREAM_WRITER_CLASS_NAME = "javax.xml.stream.XMLStreamWriter";
private static final String XML_EVENT_WRITER_CLASS_NAME = "javax.xml.stream.XMLEventWriter";
private static final String DOM_TO_STREAM_WRITER_CLASS_NAME = "org.eclipse.persistence.internal.oxm.record.DomToXMLStreamWriter";
private static final String DOM_TO_EVENT_WRITER_CLASS_NAME = "org.eclipse.persistence.internal.oxm.record.DomToXMLEventWriter";
private static final String WRITE_TO_STREAM_METHOD_NAME = "writeToStream";
private static final String WRITE_TO_EVENT_WRITER_METHOD_NAME = "writeToEventWriter";
protected static Class staxResultClass;
protected static Method staxResultGetStreamWriterMethod;
protected static Method staxResultGetEventWriterMethod;
private static Constructor xmlStreamWriterRecordConstructor;
private static Constructor xmlEventWriterRecordConstructor;
protected static Method writeToStreamMethod;
protected static Method writeToEventWriterMethod;
protected static Class domToStreamWriterClass;
protected static Class domToEventWriterClass;
static {
try {
staxResultClass = PrivilegedAccessHelper.getClassForName(STAX_RESULT_CLASS_NAME);
if(staxResultClass != null) {
staxResultGetStreamWriterMethod = PrivilegedAccessHelper.getDeclaredMethod(staxResultClass, GET_XML_STREAM_WRITER_METHOD_NAME, new Class[]{});
staxResultGetEventWriterMethod = PrivilegedAccessHelper.getDeclaredMethod(staxResultClass, GET_XML_EVENT_WRITER_METHOD_NAME, new Class[]{});
}
Class streamWriterRecordClass = PrivilegedAccessHelper.getClassForName(XML_STREAM_WRITER_RECORD_CLASS_NAME);
Class streamWriterClass = PrivilegedAccessHelper.getClassForName(XML_STREAM_WRITER_CLASS_NAME);
xmlStreamWriterRecordConstructor = PrivilegedAccessHelper.getConstructorFor(streamWriterRecordClass, new Class[]{streamWriterClass}, true);
Class eventWriterRecordClass = PrivilegedAccessHelper.getClassForName(XML_EVENT_WRITER_RECORD_CLASS_NAME);
Class eventWriterClass = PrivilegedAccessHelper.getClassForName(XML_EVENT_WRITER_CLASS_NAME);
xmlEventWriterRecordConstructor = PrivilegedAccessHelper.getConstructorFor(eventWriterRecordClass, new Class[]{eventWriterClass}, true);
domToStreamWriterClass = PrivilegedAccessHelper.getClassForName(DOM_TO_STREAM_WRITER_CLASS_NAME);
writeToStreamMethod = PrivilegedAccessHelper.getMethod(domToStreamWriterClass, WRITE_TO_STREAM_METHOD_NAME, new Class[] {CoreClassConstants.NODE, CoreClassConstants.STRING, CoreClassConstants.STRING, streamWriterClass}, true);
domToEventWriterClass = PrivilegedAccessHelper.getClassForName(DOM_TO_EVENT_WRITER_CLASS_NAME);
writeToEventWriterMethod = PrivilegedAccessHelper.getMethod(domToEventWriterClass, WRITE_TO_EVENT_WRITER_METHOD_NAME, new Class[] {CoreClassConstants.NODE, CoreClassConstants.STRING, CoreClassConstants.STRING, eventWriterClass}, true);
} catch (Exception ex) {
// Do nothing
}
}
protected XMLAttachmentMarshaller attachmentMarshaller;
private String attributePrefix;
private boolean fragment;
private boolean includeRoot = true;
private boolean marshalEmptyCollections = true;
protected MEDIA_TYPE mediaType;
private char namespaceSeparator;
private String noNamespaceSchemaLocation;
private boolean reduceAnyArrays;
private Schema schema;
private String schemaLocation;
protected XMLTransformer transformer;
private String valueWrapper;
private boolean wrapperAsCollectionName = false;
private String xmlHeader;
private Object marshalAttributeGroup;
public XMLMarshaller(CONTEXT context) {
super(context);
this.includeRoot = true;
this.marshalEmptyCollections = true;
this.namespaceSeparator = Constants.DOT;
this.reduceAnyArrays = false;
this.valueWrapper = Constants.VALUE_WRAPPER;
}
/**
* Copy constructor
*/
protected XMLMarshaller(XMLMarshaller xmlMarshaller) {
super(xmlMarshaller);
attachmentMarshaller = xmlMarshaller.getAttachmentMarshaller();
attributePrefix = xmlMarshaller.getAttributePrefix();
fragment = xmlMarshaller.isFragment();
includeRoot = xmlMarshaller.isIncludeRoot();
marshalEmptyCollections = xmlMarshaller.isMarshalEmptyCollections();
mediaType = (MEDIA_TYPE) xmlMarshaller.mediaType;
namespaceSeparator = xmlMarshaller.getNamespaceSeparator();
noNamespaceSchemaLocation = xmlMarshaller.getNoNamespaceSchemaLocation();
reduceAnyArrays = xmlMarshaller.isReduceAnyArrays();
if(null != xmlMarshaller.getSchema()) {
setSchema(xmlMarshaller.getSchema());
}
schemaLocation = xmlMarshaller.getSchemaLocation();
valueWrapper = xmlMarshaller.getValueWrapper();
wrapperAsCollectionName = xmlMarshaller.isWrapperAsCollectionName();
xmlHeader = xmlMarshaller.getXmlHeader();
}
protected void addDescriptorNamespacesToXMLRecord(DESCRIPTOR xmlDescriptor, AbstractMarshalRecord record) {
if (null == xmlDescriptor) {
return;
}
copyNamespaces(xmlDescriptor.getNamespaceResolver(), record.getNamespaceResolver());
}
private XPathFragment buildRootFragment(Object object, DESCRIPTOR descriptor, boolean isXMLRoot, MarshalRecord marshalRecord) {
XPathFragment rootFragment = null;
if (isXMLRoot) {
String xmlRootUri = ((Root) object).getNamespaceURI();
String xmlRootLocalName = ((Root) object).getLocalName();
rootFragment = new XPathFragment();
rootFragment.setLocalName(xmlRootLocalName);
rootFragment.setNamespaceURI(xmlRootUri);
rootFragment.setNamespaceAware(marshalRecord.isNamespaceAware());
rootFragment.setNamespaceSeparator(marshalRecord.getNamespaceSeparator());
if (xmlRootUri != null) {
if (descriptor != null) {
String xmlRootPrefix = marshalRecord.getNamespaceResolver().resolveNamespaceURI(xmlRootUri);
if (xmlRootPrefix == null && !(xmlRootUri.equals(marshalRecord.getNamespaceResolver().getDefaultNamespaceURI()))) {
xmlRootPrefix = marshalRecord.getNamespaceResolver().generatePrefix();
marshalRecord.getNamespaceResolver().put(xmlRootPrefix, xmlRootUri);
}
if(xmlRootPrefix == null) {
rootFragment.setXPath(xmlRootLocalName);
} else {
rootFragment.setPrefix(xmlRootPrefix);
}
} else {
if(marshalRecord.isNamespaceAware()){
String xmlRootPrefix = "ns0";
marshalRecord.getNamespaceResolver().put(xmlRootPrefix, xmlRootUri);
rootFragment.setXPath(xmlRootPrefix + marshalRecord.getNamespaceSeparator() + xmlRootLocalName);
}else{
rootFragment.setXPath(xmlRootLocalName);
}
}
}
} else {
Field defaultRootField = (Field) descriptor.getDefaultRootElementField();
if(defaultRootField != null){
rootFragment = defaultRootField.getXPathFragment();
}
}
return rootFragment;
}
protected void copyNamespaces(NamespaceResolver source, NamespaceResolver target) {
if (null != source && null != target) {
if(source.hasPrefixesToNamespaces()) {
target.getPrefixesToNamespaces().putAll(source.getPrefixesToNamespaces());
}
target.setDefaultNamespaceURI(source.getDefaultNamespaceURI());
}
}
@Override
public XMLAttachmentMarshaller getAttachmentMarshaller() {
return this.attachmentMarshaller;
}
/**
* Value that will be used to prefix attributes.
* Ignored marshalling XML.
* @since 2.4
*/
public String getAttributePrefix() {
return attributePrefix;
}
/**
* INTERNAL:
* Return the descriptor for the root object.
*/
protected DESCRIPTOR getDescriptor(Class clazz, ABSTRACT_SESSION session) throws XMLMarshalException {
DESCRIPTOR descriptor = (DESCRIPTOR) session.getDescriptor(clazz);
if (descriptor == null) {
throw XMLMarshalException.descriptorNotFoundInProject(clazz.getName());
}
return descriptor;
}
/**
* INTERNAL:
* Return the descriptor for the root object.
*/
public DESCRIPTOR getDescriptor(Object object) throws XMLMarshalException {
DESCRIPTOR descriptor = (DESCRIPTOR) context.getSession(object).getDescriptor(object);
if (descriptor == null) {
throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
}
return descriptor;
}
/**
* INTERNAL:
* Return the descriptor for the root object.
*/
protected DESCRIPTOR getDescriptor(Object object, ABSTRACT_SESSION session) throws XMLMarshalException {
DESCRIPTOR descriptor = (DESCRIPTOR) session.getDescriptor(object);
if (descriptor == null) {
throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
}
return descriptor;
}
protected DESCRIPTOR getDescriptor(Object object, boolean isXMLRoot) {
if (isXMLRoot) {
return getDescriptor((Root) object);
} else {
return getDescriptor(object);
}
}
protected DESCRIPTOR getDescriptor(Root object) throws XMLMarshalException {
DESCRIPTOR descriptor = null;
try {
ABSTRACT_SESSION session = context.getSession(object.getObject());
if(null == session) {
return null;
}
descriptor = (DESCRIPTOR) session.getDescriptor(object.getObject());
} catch (XMLMarshalException marshalException) {
if ((descriptor == null) && isSimpleXMLRoot(object)) {
return null;
}
throw marshalException;
}
if (descriptor == null) {
throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
}
return descriptor;
}
protected DESCRIPTOR getDescriptor(Root object, ABSTRACT_SESSION session) throws XMLMarshalException {
DESCRIPTOR descriptor = null;
try {
if(null == session) {
return null;
}
descriptor = (DESCRIPTOR) session.getDescriptor(object.getObject());
} catch (XMLMarshalException marshalException) {
if ((descriptor == null) && isSimpleXMLRoot(object)) {
return null;
}
throw marshalException;
}
if (descriptor == null) {
throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
}
return descriptor;
}
protected Node getNode(Object object, Node parentNode, ABSTRACT_SESSION session, DESCRIPTOR descriptor, boolean isRoot) {
if(isRoot) {
object = ((Root) object).getObject();
if(object instanceof Node) {
return (Node) object;
}
}
return null;
}
/**
* Get the no namespace schema location set on this XMLMarshaller
* @return the no namespace schema location specified on this XMLMarshaller
*/
public String getNoNamespaceSchemaLocation() {
return noNamespaceSchemaLocation;
}
public Schema getSchema() {
return schema;
}
/**
* INTERNAL
* @return the transformer instance for this marshaller
*/
@Override
public XMLTransformer getTransformer() {
if(null == transformer) {
XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
transformer = xmlPlatform.newXMLTransformer();
transformer.setEncoding(getEncoding());
transformer.setFormattedOutput(isFormattedOutput());
transformer.setFragment(fragment);
}
return transformer;
}
/**
* Name of the property to marshal/unmarshal as a wrapper on the text() mappings
* Ignored marshalling XML.
* @since 2.4
*/
public String getValueWrapper() {
return valueWrapper;
}
/**
* Get this Marshaller's XML Header.
* @since 2.4
*/
public String getXmlHeader() {
return xmlHeader;
}
/**
* Get the schema location set on this XMLMarshaller
* @return the schema location specified on this XMLMarshaller
*/
public String getSchemaLocation() {
return schemaLocation;
}
/**
* INTERNAL
* @return true if the media type is application/json, else false.
* @since EclipseLink 2.6.0
*/
@Override
public boolean isApplicationJSON() {
return null != mediaType && mediaType.isApplicationJSON();
}
/**
* INTERNAL
* @return true if the media type is application/xml, else false.
* @since EclipseLink 2.6.0
*/
@Override
public boolean isApplicationXML() {
return null == mediaType || mediaType.isApplicationXML();
}
/**
* PUBLIC:
* Returns if this should marshal to a fragment. If true an XML header string is not written out.
* @return if this should marshal to a fragment or not
*/
public boolean isFragment() {
return isApplicationXML() && fragment;
}
/**
* Determine if the @XMLRootElement should be marshalled when present.
* Ignored marshalling XML.
* @return
* @since 2.4
*/
@Override
public boolean isIncludeRoot() {
if(isApplicationJSON()){
return includeRoot;
}
return true;
}
/**
* Property to determine if size 1 any collections should be treated as collections
* Ignored marshalling XML.
*/
@Override
public boolean isReduceAnyArrays() {
return reduceAnyArrays;
}
/**
* Get the namespace separator used during marshal operations.
* If mediaType is application/json '.' is the default
* Ignored marshalling XML.
* @since 2.4
*/
public char getNamespaceSeparator() {
return namespaceSeparator;
}
/**
* Name of the property to determine if empty collections should be marshalled as []
* Ignored marshalling XML.
* @since 2.4
*/
public boolean isMarshalEmptyCollections() {
return marshalEmptyCollections;
}
public boolean isWrapperAsCollectionName() {
return wrapperAsCollectionName;
}
protected boolean isSimpleXMLRoot(Root xmlRoot) {
Class xmlRootObjectClass = xmlRoot.getObject().getClass();
ConversionManager conversionManager = (ConversionManager) context.getSession().getDatasourcePlatform().getConversionManager();
if (conversionManager.schemaType(xmlRootObjectClass) != null || CoreClassConstants.List_Class.isAssignableFrom(xmlRootObjectClass) || CoreClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(xmlRootObjectClass) || CoreClassConstants.DURATION.isAssignableFrom(xmlRootObjectClass)) {
return true;
} else if(xmlRoot.getObject() instanceof org.w3c.dom.Node) {
return true;
}
return false;
}
/**
* PUBLIC:
* Convert the given object to XML and update the given contentHandler with that XML Document
* @param object the object to marshal
* @param contentHandler the contentHandler which the specified object should be marshalled to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, ContentHandler contentHandler) throws XMLMarshalException {
marshal(object, contentHandler, null);
}
/**
* PUBLIC:
* Convert the given object to XML and update the given contentHandler with that XML Document
* @param object the object to marshal
* @param contentHandler the contentHandler which the specified object should be marshalled to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, ContentHandler contentHandler, LexicalHandler lexicalHandler) throws XMLMarshalException {
if(object instanceof JSONWithPadding && !isApplicationJSON()){
object = ((JSONWithPadding)object).getObject();
}
if ((object == null) || (contentHandler == null)) {
throw XMLMarshalException.nullArgumentException();
}
ABSTRACT_SESSION session = null;
DESCRIPTOR xmlDescriptor = null;
boolean isXMLRoot = (object instanceof Root);
if(isXMLRoot){
try{
session = context.getSession(((Root)object).getObject());
if(session != null){
xmlDescriptor = getDescriptor(((Root)object).getObject(), session);
}
}catch (XMLMarshalException marshalException) {
if (!isSimpleXMLRoot((Root) object)) {
throw marshalException;
}
}
}else{
Class objectClass = object.getClass();
session = context.getSession(objectClass);
xmlDescriptor = getDescriptor(objectClass, session);
}
ContentHandlerRecord contentHandlerRecord = new ContentHandlerRecord();
contentHandlerRecord.setMarshaller(this);
contentHandlerRecord.setContentHandler(contentHandler);
contentHandlerRecord.setLexicalHandler(lexicalHandler);
marshal(object, contentHandlerRecord, session, xmlDescriptor,isXMLRoot);
}
/**
* Convert the given object to XML and update the given marshal record with
* that XML Document.
* @param object the object to marshal
* @param marshalRecord the marshalRecord to marshal the object to
*/
public void marshal(Object object, MarshalRecord marshalRecord) {
if(object instanceof JSONWithPadding && !isApplicationJSON()){
object = ((JSONWithPadding)object).getObject();
}
if ((object == null) || (marshalRecord == null)) {
throw XMLMarshalException.nullArgumentException();
}
boolean isXMLRoot = (object instanceof Root);
ABSTRACT_SESSION session = null;
DESCRIPTOR xmlDescriptor = null;
if(isXMLRoot){
try{
session = context.getSession(((Root)object).getObject());
if(session != null){
xmlDescriptor = getDescriptor(((Root)object).getObject(), session);
}
}catch (XMLMarshalException marshalException) {
if (!isSimpleXMLRoot((Root) object)) {
throw marshalException;
}
}
}else{
Class objectClass = object.getClass();
session = context.getSession(objectClass);
xmlDescriptor = getDescriptor(objectClass, session);
}
marshal(object, marshalRecord, session, xmlDescriptor, isXMLRoot);
}
/**
* Convert the given object to XML and update the given marshal record with
* that XML Document.
* @param object the object to marshal
* @param marshalRecord the marshalRecord to marshal the object to
* @param descriptor the XMLDescriptor for the object being marshalled
*/
protected void marshal(Object object, MarshalRecord marshalRecord, ABSTRACT_SESSION session, DESCRIPTOR descriptor, boolean isXMLRoot) {
if(null != schema) {
marshalRecord = new ValidatingMarshalRecord(marshalRecord, this);
}
if (this.attachmentMarshaller != null) {
marshalRecord.setXOPPackage(this.attachmentMarshaller.isXOPPackage());
}
marshalRecord.setMarshaller(this);
Root root = null;
if(isXMLRoot) {
root = (Root) object;
}
Node node = getNode(object, marshalRecord.getDOM(), session, descriptor, isXMLRoot);
if(this.mapper == null) {
if(null == node) {
addDescriptorNamespacesToXMLRecord(descriptor, marshalRecord);
}
} else {
if(descriptor == null || null != node){
marshalRecord.setNamespaceResolver(new PrefixMapperNamespaceResolver(mapper, null));
}else{
marshalRecord.setNamespaceResolver(new PrefixMapperNamespaceResolver(mapper, descriptor.getNamespaceResolver()));
}
marshalRecord.setCustomNamespaceMapper(true);
}
if(this.getMarshalAttributeGroup() != null) {
if(marshalAttributeGroup.getClass() == CoreClassConstants.STRING) {
CoreAttributeGroup group = descriptor.getAttributeGroup((String)marshalAttributeGroup);
if(group != null) {
marshalRecord.pushAttributeGroup(group);
} else {
throw XMLMarshalException.invalidAttributeGroupName((String)marshalAttributeGroup, descriptor.getJavaClassName());
}
} else if(marshalAttributeGroup instanceof CoreAttributeGroup) {
marshalRecord.pushAttributeGroup((CoreAttributeGroup)marshalAttributeGroup);
} else {
//Error case
}
}
NamespaceResolver nr = marshalRecord.getNamespaceResolver();
if(node != null) {
if(isXMLRoot) {
if (isFragment()) {
marshalRecord.node(node, null, root.getNamespaceURI(), root.getLocalName());
} else {
String encoding = root.getEncoding();
if(null == encoding) {
encoding = Constants.DEFAULT_XML_ENCODING;
}
String version = root.getXMLVersion();
if(null == version) {
version = DEFAULT_XML_VERSION;
}
marshalRecord.startDocument(encoding, version);
marshalRecord.node(node, marshalRecord.getNamespaceResolver(), root.getNamespaceURI(), root.getLocalName());
marshalRecord.endDocument();
}
} else {
marshalRecord.node(node, nr);
}
marshalRecord.flush();
return;
}
if(isXMLRoot){
if(descriptor != null){
marshalRecord.beforeContainmentMarshal(root.getObject());
}
}else{
marshalRecord.beforeContainmentMarshal(object);
}
if (!isFragment()) {
String encoding = getEncoding();
String version = DEFAULT_XML_VERSION;
if (!isXMLRoot && descriptor!= null) {
marshalRecord.setLeafElementType(descriptor.getDefaultRootElementType());
} else {
if (root.getEncoding() != null) {
encoding = root.getEncoding();
}
if (root.getXMLVersion() != null) {
version = root.getXMLVersion();
}
}
marshalRecord.startDocument(encoding, version);
}
if (getXmlHeader() != null) {
marshalRecord.writeHeader();
}
if(isXMLRoot) {
if(root.getObject() instanceof Node) {
marshalRecord.node((Node)root.getObject(), new NamespaceResolver(), root.getNamespaceURI(), root.getLocalName());
marshalRecord.endDocument();
return;
}
}
XPathFragment rootFragment = buildRootFragment(object, descriptor, isXMLRoot, marshalRecord);
String schemaLocation = getSchemaLocation();
String noNsSchemaLocation = getNoNamespaceSchemaLocation();
boolean isNil = false;
if (isXMLRoot) {
object = root.getObject();
if (root.getSchemaLocation() != null) {
schemaLocation = root.getSchemaLocation();
}
if (root.getNoNamespaceSchemaLocation() != null) {
noNsSchemaLocation = root.getNoNamespaceSchemaLocation();
}
marshalRecord.setLeafElementType(root.getSchemaType());
isNil = root.isNil();
}
String xsiPrefix = null;
if ((null != getSchemaLocation()) || (null != getNoNamespaceSchemaLocation()) || (isNil)) {
xsiPrefix = nr.resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
if (null == xsiPrefix) {
xsiPrefix = Constants.SCHEMA_INSTANCE_PREFIX;
nr.put(Constants.SCHEMA_INSTANCE_PREFIX, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
}
OBJECT_BUILDER treeObjectBuilder = null;
if (descriptor != null) {
treeObjectBuilder = (OBJECT_BUILDER) descriptor.getObjectBuilder();
}
if(session == null){
session = (ABSTRACT_SESSION) context.getSession();
}
marshalRecord.setSession(session);
if (null != rootFragment && !(rootFragment.getLocalName().equals(Constants.EMPTY_STRING))) {
marshalRecord.startPrefixMappings(nr);
if (!isXMLRoot && descriptor != null && descriptor.getNamespaceResolver() == null && rootFragment.hasNamespace()) {
// throw an exception if the name has a : in it but the namespaceresolver is null
throw XMLMarshalException.namespaceResolverNotSpecified(rootFragment.getShortName());
}
if(isIncludeRoot()){
marshalRecord.openStartElement(rootFragment, nr);
}
if (null != schemaLocation) {
marshalRecord.attributeWithoutQName(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_LOCATION, xsiPrefix, schemaLocation);
}
if (null != noNsSchemaLocation) {
marshalRecord.attributeWithoutQName(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.NO_NS_SCHEMA_LOCATION, xsiPrefix, noNsSchemaLocation);
}
if (isNil) {
marshalRecord.nilSimple(nr);
}
marshalRecord.namespaceDeclarations(nr);
if (descriptor != null && !isNil) {
marshalRecord.addXsiTypeAndClassIndicatorIfRequired(descriptor, null, descriptor.getDefaultRootElementField(), root, object, isXMLRoot, true);
treeObjectBuilder.marshalAttributes(marshalRecord, object, session);
}
if(isIncludeRoot()) {
marshalRecord.closeStartElement();
}
}else{
//no rootfragment
marshalRecord.marshalWithoutRootElement(treeObjectBuilder,object, descriptor, root, isXMLRoot);
}
if (treeObjectBuilder != null && !isNil) {
treeObjectBuilder.buildRow(marshalRecord, object, session, this, rootFragment);
} else if (isXMLRoot) {
if(object != null && !isNil) {
if(root.getDeclaredType() != null && root.getObject() != null && root.getDeclaredType() != root.getObject().getClass()) {
QName type = marshalRecord.getConversionManager().schemaType(object.getClass());
if(type != null) {
xsiPrefix = nr.resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
if (null == xsiPrefix) {
xsiPrefix = Constants.SCHEMA_INSTANCE_PREFIX;
marshalRecord.namespaceDeclaration(xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
marshalRecord.namespaceDeclaration(Constants.SCHEMA_PREFIX, javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
String typeValue = type.getLocalPart();
if(marshalRecord.isNamespaceAware() && (mediaType.isApplicationXML() || getJsonTypeConfiguration().useXsdTypesWithPrefix())){
typeValue = Constants.SCHEMA_PREFIX + marshalRecord.getNamespaceSeparator() + typeValue;
}
marshalRecord.attribute(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE, xsiPrefix + Constants.COLON + Constants.SCHEMA_TYPE_ATTRIBUTE, typeValue);
}
}
marshalRecord.characters(root.getSchemaType(), object, null, false);
}
}
if (null != rootFragment && !(rootFragment.getLocalName().equals(Constants.EMPTY_STRING)) && isIncludeRoot()) {
marshalRecord.endElement(rootFragment, nr);
marshalRecord.endPrefixMappings(nr);
}
if (!isFragment() ) {
marshalRecord.endDocument();
}
if(isXMLRoot){
if(descriptor != null){
marshalRecord.afterContainmentMarshal(null, root.getObject());
}
}else{
marshalRecord.afterContainmentMarshal(null, object);
}
}
/**
* PUBLIC:
* @param object the object to marshal
* @param node the node which the specified object should be marshalled to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, Node node) throws XMLMarshalException {
if(object instanceof JSONWithPadding && !isApplicationJSON()){
object = ((JSONWithPadding)object).getObject();
}
if ((object == null) || (node == null)) {
throw XMLMarshalException.nullArgumentException();
}
ABSTRACT_SESSION session = null;
DESCRIPTOR xmlDescriptor = null;
boolean isXMLRoot = (object instanceof Root);
if(isXMLRoot){
try{
session = context.getSession(((Root)object).getObject());
if(session != null){
xmlDescriptor = getDescriptor(((Root)object).getObject(), session);
}
}catch (XMLMarshalException marshalException) {
if (!isSimpleXMLRoot((Root) object)) {
throw marshalException;
}
}
}else{
Class objectClass = object.getClass();
session = context.getSession(objectClass);
xmlDescriptor = getDescriptor(objectClass, session);
}
NodeRecord contentHandlerRecord = new NodeRecord(node);
contentHandlerRecord.setMarshaller(this);
if (!isXMLRoot) {
if ((null == xmlDescriptor.getDefaultRootElement()) && (node.getNodeType() == Node.ELEMENT_NODE) && (xmlDescriptor.getSchemaReference() != null) && (xmlDescriptor.getSchemaReference().getType() == XMLSchemaReference.COMPLEX_TYPE)) {
Attr typeAttr = ((Element) node).getAttributeNodeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE);
if (typeAttr == null) {
NamespaceResolver namespaceResolver = xmlDescriptor.getNonNullNamespaceResolver();
String xsiPrefix = namespaceResolver.resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
if (null == xsiPrefix) {
xsiPrefix = namespaceResolver.generatePrefix(Constants.SCHEMA_INSTANCE_PREFIX);
}
String value = xmlDescriptor.getSchemaReference().getSchemaContext();
((Element) node).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
((Element) node).setAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, xsiPrefix + Constants.COLON + Constants.SCHEMA_TYPE_ATTRIBUTE, value);
} else {
String value = xmlDescriptor.getSchemaReference().getSchemaContext();
typeAttr.setValue(value);
}
}
}
marshal(object, contentHandlerRecord, session, xmlDescriptor,isXMLRoot);
}
/**
* PUBLIC:
* Convert the given object to XML and update the given outputStream with that XML Document
* @param object the object to marshal
* @param outputStream the outputStream to marshal the object to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, OutputStream outputStream) throws XMLMarshalException {
marshal (object, outputStream, null, null);
}
private void marshal(Object object, OutputStream outputStream, ABSTRACT_SESSION session, DESCRIPTOR xmlDescriptor) throws XMLMarshalException {
if ((object == null) || (outputStream == null)) {
throw XMLMarshalException.nullArgumentException();
}
boolean isXMLRoot = false;
String version = DEFAULT_XML_VERSION;
String encoding = getEncoding();
String callbackName = null;
if(object instanceof JSONWithPadding){
callbackName = ((JSONWithPadding)object).getCallbackName();
object = ((JSONWithPadding)object).getObject();
if(object == null){
throw XMLMarshalException.nullArgumentException();
}
}
if (object instanceof Root) {
isXMLRoot = true;
Root xroot = (Root) object;
version = xroot.getXMLVersion() != null ? xroot.getXMLVersion() : version;
encoding = xroot.getEncoding() != null ? xroot.getEncoding() : encoding;
}
if(!encoding.equals(Constants.DEFAULT_XML_ENCODING)) {
try {
OutputStreamWriter writer = new OutputStreamWriter(outputStream, encoding);
marshal(object, writer, session, xmlDescriptor);
writer.flush();
} catch(EclipseLinkException e) {
throw e;
} catch(Exception e) {
throw XMLMarshalException.marshalException(e);
}
return;
}
MarshalRecord marshalRecord;
if (isFormattedOutput()) {
if(isApplicationJSON()) {
marshalRecord = new JSONFormattedWriterRecord(outputStream, callbackName);
} else {
marshalRecord = new FormattedOutputStreamRecord();
((FormattedOutputStreamRecord)marshalRecord).setOutputStream(outputStream);
}
} else {
if(isApplicationJSON()) {
marshalRecord = new JSONWriterRecord(outputStream, callbackName);
} else {
marshalRecord = new OutputStreamRecord();
((OutputStreamRecord)marshalRecord).setOutputStream(outputStream);
}
}
marshalStreamOrWriter(object, marshalRecord, session, xmlDescriptor, isXMLRoot);
}
/**
* PUBLIC:
* Convert the given object to XML and update the given result with that XML Document
* @param object the object to marshal
* @param result the result to marshal the object to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, Result result) throws XMLMarshalException {
if ((object == null) || (result == null)) {
throw XMLMarshalException.nullArgumentException();
}
DESCRIPTOR xmlDescriptor = null;
ABSTRACT_SESSION session = null;
boolean isXMLRoot = (object instanceof Root);
if(isXMLRoot){
try{
session = context.getSession(((Root)object).getObject());
if(session != null){
xmlDescriptor = getDescriptor(((Root)object).getObject(), session);
}
}catch (XMLMarshalException marshalException) {
if (!isSimpleXMLRoot((Root) object)) {
throw marshalException;
}
}
}else{
Class objectClass = object.getClass();
session = context.getSession(objectClass);
xmlDescriptor = getDescriptor(objectClass, session);
}
//if this is a simple xml root, the session and descriptor will be null
if (result instanceof StreamResult) {
StreamResult streamResult = (StreamResult) result;
Writer writer = streamResult.getWriter();
if (writer != null) {
marshal(object, writer, session, xmlDescriptor);
} else if (streamResult.getOutputStream() != null) {
marshal(object, streamResult.getOutputStream(), session, xmlDescriptor);
} else {
try {
File f;
try {
f = new File(new URL(streamResult.getSystemId()).toURI());
} catch(MalformedURLException malformedURLException) {
try {
f = new File(streamResult.getSystemId());
} catch(Exception e) {
throw malformedURLException;
}
}
writer = new FileWriter(f);
try {
marshal(object, writer, session, xmlDescriptor);
} finally {
writer.close();
}
} catch (Exception e) {
throw XMLMarshalException.marshalException(e);
}
}
}else if (result instanceof DOMResult) {
DOMResult domResult = (DOMResult) result;
// handle case where the node is null
if (domResult.getNode() == null) {
domResult.setNode(this.objectToXML(object));
} else {
marshal(object, domResult.getNode());
}
} else if (result instanceof SAXResult) {
SAXResult saxResult = (SAXResult) result;
marshal(object, saxResult.getHandler());
} else if (result instanceof ExtendedResult){
marshal(object, ((ExtendedResult)result).createRecord(), session, xmlDescriptor, isXMLRoot);
}else {
if (result.getClass().equals(staxResultClass)) {
try {
Object xmlStreamWriter = PrivilegedAccessHelper.invokeMethod(staxResultGetStreamWriterMethod, result);
if (xmlStreamWriter != null) {
MarshalRecord record = (MarshalRecord)PrivilegedAccessHelper.invokeConstructor(xmlStreamWriterRecordConstructor, new Object[]{xmlStreamWriter});
record.setMarshaller(this);
marshal(object, record, session, xmlDescriptor, isXMLRoot);
return;
} else {
Object xmlEventWriter = PrivilegedAccessHelper.invokeMethod(staxResultGetEventWriterMethod, result);
if(xmlEventWriter != null) {
MarshalRecord record = (MarshalRecord)PrivilegedAccessHelper.invokeConstructor(xmlEventWriterRecordConstructor, new Object[]{xmlEventWriter});
record.setMarshaller(this);
marshal(object, record, session, xmlDescriptor, isXMLRoot);
return;
}
}
} catch(EclipseLinkException e) {
throw e;
} catch (Exception e) {
throw XMLMarshalException.marshalException(e);
}
}
java.io.StringWriter writer = new java.io.StringWriter();
marshal(object, writer);
javax.xml.transform.stream.StreamSource source = new javax.xml.transform.stream.StreamSource(new java.io.StringReader(writer.toString()));
getTransformer().transform(source, result);
}
return;
}
/**
* PUBLIC:
* Convert the given object to XML and update the given writer with that XML Document
* @param object the object to marshal
* @param writer the writer to marshal the object to
* @throws XMLMarshalException if an error occurred during marshalling
*/
public void marshal(Object object, Writer writer) throws XMLMarshalException {
marshal(object, writer, null, null);
}
private void marshal(Object object, Writer writer, ABSTRACT_SESSION session, DESCRIPTOR xmlDescriptor) throws XMLMarshalException {
if ((object == null) || (writer == null)) {
throw XMLMarshalException.nullArgumentException();
}
boolean isXMLRoot = false;
String version = DEFAULT_XML_VERSION;
String encoding = getEncoding();
String callbackName = null;
if(object instanceof JSONWithPadding){
callbackName = ((JSONWithPadding)object).getCallbackName();
object = ((JSONWithPadding)object).getObject();
if(object == null){
throw XMLMarshalException.nullArgumentException();
}
}
if (object instanceof Root) {
isXMLRoot = true;
Root xroot = (Root) object;
version = xroot.getXMLVersion() != null ? xroot.getXMLVersion() : version;
encoding = xroot.getEncoding() != null ? xroot.getEncoding() : encoding;
}
MarshalRecord marshalRecord;
writer = wrapWriter(writer);
if (isFormattedOutput()) {
if(isApplicationJSON()) {
marshalRecord = new JSONFormattedWriterRecord(writer, callbackName);
} else {
marshalRecord = new FormattedWriterRecord();
((FormattedWriterRecord) marshalRecord).setWriter(writer);
}
} else {
if(isApplicationJSON()) {
marshalRecord = new JSONWriterRecord(writer, callbackName);
} else {
marshalRecord = new WriterRecord();
((WriterRecord) marshalRecord).setWriter(writer);
}
}
marshalStreamOrWriter(object, marshalRecord, session, xmlDescriptor, isXMLRoot);
}
private void marshalStreamOrWriter(Object object, MarshalRecord marshalRecord, ABSTRACT_SESSION session, DESCRIPTOR descriptor, boolean isXMLRoot) {
marshalRecord.setMarshaller(this);
String rootName = null;
String rootNamespace = null;
if(isXMLRoot){
rootName = ((Root)object).getLocalName();
rootNamespace = ((Root)object).getNamespaceURI();
if(session == null || descriptor == null){
try{
session = context.getSession(((Root)object).getObject());
if(session != null){
descriptor = getDescriptor(((Root)object).getObject(), session);
}
}catch (XMLMarshalException marshalException) {
if (!isSimpleXMLRoot((Root) object)) {
throw marshalException;
}
}
}
}else{
Class objectClass = object.getClass();
if(object instanceof Collection) {
marshalRecord.startCollection();
for(Object o : (Collection) object) {
marshal(o, marshalRecord);
}
marshalRecord.endCollection();
marshalRecord.flush();
return;
} else if(objectClass.isArray()) {
marshalRecord.startCollection();
int arrayLength = Array.getLength(object);
for(int x=0; x
* Set this Marshaller's XML Header. This header string will appear after
* the XML processing instruction (<?xml ...>), but before the start
* of the document's data.
*
*
*
* This feature is only supported when marshalling to Stream, Writer,
* or StreamResult.
*
* @since 2.4
*/
public void setXmlHeader(String xmlHeader) {
this.xmlHeader = xmlHeader;
}
public void setMarshalAttributeGroup(Object group) {
this.marshalAttributeGroup = group;
}
public Object getMarshalAttributeGroup() {
return this.marshalAttributeGroup;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy