All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler Maven / Gradle / Ivy

There is a newer version: 4.0.2
Show newest version
/*
 * Copyright (c) 1998, 2018 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 v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm.record;

import java.lang.reflect.Modifier;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.exceptions.DescriptorException;
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.Constants;
import org.eclipse.persistence.internal.oxm.Context;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.Unmarshaller;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathQName;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.internal.oxm.record.namespaces.StackUnmarshalNamespaceResolver;
import org.eclipse.persistence.internal.oxm.record.namespaces.UnmarshalNamespaceResolver;
import org.eclipse.persistence.internal.oxm.unmapped.UnmappedContentHandler;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.platform.xml.SAXDocumentBuilder;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.Locator2;

/**
 * INTERNAL:
 * 

Purpose:An implementation of ContentHandler used to handle the root element of an * XML Document during unmarshal. *

Responsibilities:

    *
  • Implement ContentHandler interface
  • *
  • Handle startElement event for the root-level element of an xml document
  • *
  • Handle inheritance, and descriptor lookup to determine the correct class associated with * this XML Element.
  • *
* * @author bdoughan * */ public class SAXUnmarshallerHandler implements ExtendedContentHandler { private XMLReader xmlReader; private Context xmlContext; private UnmarshalRecord rootRecord; private Object object; private Descriptor descriptor; private boolean shouldWrap; private Unmarshaller unmarshaller; private CoreAbstractSession session; private UnmarshalNamespaceResolver unmarshalNamespaceResolver; private UnmarshalKeepAsElementPolicy keepAsElementPolicy = new UnmarshalKeepAsElementPolicy() { @Override public boolean isKeepAllAsElement() { return false; } @Override public boolean isKeepNoneAsElement() { return true; } @Override public boolean isKeepUnknownAsElement() { return false; } }; private SAXDocumentBuilder documentBuilder; private Locator2 locator; private boolean isNil; public SAXUnmarshallerHandler(Context xmlContext) { super(); this.xmlContext = xmlContext; this.shouldWrap = true; unmarshalNamespaceResolver = new StackUnmarshalNamespaceResolver(); } public XMLReader getXMLReader() { return this.xmlReader; } public void setXMLReader(XMLReader xmlReader) { this.xmlReader = xmlReader; } public Object getObject() { if(object == null) { if(this.descriptor != null) { if(this.unmarshaller.isResultAlwaysXMLRoot() || descriptor.isResultAlwaysXMLRoot() || shouldWrap){ object = this.descriptor.wrapObjectInXMLRoot(this.rootRecord, (this.unmarshaller.isResultAlwaysXMLRoot() || descriptor.isResultAlwaysXMLRoot())); }else { object = this.rootRecord.getCurrentObject(); } } else if(documentBuilder != null) { Node node = documentBuilder.getDocument().getDocumentElement(); Root root = unmarshaller.createRoot(); root.setLocalName(node.getLocalName()); root.setNamespaceURI(node.getNamespaceURI()); root.setObject(node); object = root; } else { if(rootRecord != null) { object = this.rootRecord.getCurrentObject(); } } } return this.object; } public void setObject(Object object) { this.object = object; } @Override public void setDocumentLocator(Locator locator) { if (locator instanceof Locator2) { this.locator = (Locator2)locator; if(xmlReader != null){ xmlReader.setLocator(locator); } } } public UnmarshalNamespaceResolver getUnmarshalNamespaceResolver() { return this.unmarshalNamespaceResolver; } public void setUnmarshalNamespaceResolver(UnmarshalNamespaceResolver unmarshalNamespaceResolver) { this.unmarshalNamespaceResolver = unmarshalNamespaceResolver; } @Override public void startDocument() throws SAXException { } @Override public void endDocument() throws SAXException { } @Override public void startPrefixMapping(String prefix, String uri) throws SAXException { unmarshalNamespaceResolver.push(prefix, uri); } @Override public void endPrefixMapping(String prefix) throws SAXException { unmarshalNamespaceResolver.pop(prefix); } /** * INTERNAL: * * Resolve any mapping references. */ public void resolveReferences() { if(null != rootRecord) { rootRecord.resolveReferences(session, unmarshaller.getIDResolver()); } } @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { try { String name; if (localName == null || localName.length() == 0) { name = qName; } else { name = localName; } XPathQName rootQName; if (namespaceURI == null || namespaceURI.length() == 0) { rootQName = new XPathQName(name, xmlReader.isNamespaceAware() ); } else { rootQName = new XPathQName(namespaceURI, name, xmlReader.isNamespaceAware() ); } Class primitiveWrapperClass = null; Descriptor xmlDescriptor = xmlContext.getDescriptor(rootQName); //if no match on root element look for xsi:type if (xmlDescriptor == null || (unmarshaller.getMediaType() == MediaType.APPLICATION_JSON && unmarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName() != null && !Constants.SCHEMA_TYPE_ATTRIBUTE.equals(unmarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName()))) { boolean isPrimitiveType = false; String type = null; if(xmlReader.isNamespaceAware()){ type = atts.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE); } else if (unmarshaller.getMediaType() != MediaType.APPLICATION_JSON || unmarshaller.getJsonTypeConfiguration().useJsonTypeCompatibility()) { type = atts.getValue(Constants.EMPTY_STRING, Constants.SCHEMA_TYPE_ATTRIBUTE); } else if (unmarshaller.getMediaType() == MediaType.APPLICATION_JSON && unmarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName() != null) { type = atts.getValue(Constants.EMPTY_STRING, unmarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName()); } if (null != type) { XPathFragment typeFragment = new XPathFragment(type, xmlReader.getNamespaceSeparator(), xmlReader.isNamespaceAware()); // set the prefix using a reverse key lookup by uri value on namespaceMap if (xmlReader.isNamespaceAware() && null != unmarshalNamespaceResolver) { typeFragment.setNamespaceURI(unmarshalNamespaceResolver.getNamespaceURI(typeFragment.getPrefix())); } Descriptor lookupDescriptor = xmlContext.getDescriptorByGlobalType(typeFragment); if(lookupDescriptor == null) { QName lookupQName = null; if(typeFragment.getNamespaceURI() == null){ lookupQName= new QName(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI, typeFragment.getLocalName()); }else{ lookupQName= new QName(typeFragment.getNamespaceURI(), typeFragment.getLocalName()); } //check to see if type attribute represents simple type if(null == session) { session = (CoreAbstractSession) xmlContext.getSession(); } ConversionManager conversionManager = (ConversionManager) session.getDatasourcePlatform().getConversionManager(); primitiveWrapperClass = conversionManager.javaType(lookupQName); }else{ //found descriptor based on type attribute xmlDescriptor = lookupDescriptor; session = xmlContext.getSession(xmlDescriptor); } } } else { if(null != xmlDescriptor.getDefaultRootElementField() && !unmarshaller.isResultAlwaysXMLRoot()){ String descLocalName = xmlDescriptor.getDefaultRootElementField().getXPathFragment().getLocalName(); if( descLocalName != null && descLocalName.equals(localName) ){ String descUri = xmlDescriptor.getDefaultRootElementField().getXPathFragment().getNamespaceURI(); if(!xmlReader.isNamespaceAware() || (xmlReader.isNamespaceAware() && ((namespaceURI == null && descUri == null ) || (namespaceURI !=null &&namespaceURI.length() == 0 && descUri == null ) || (namespaceURI != null && namespaceURI.equals(descUri))))){ //found a descriptor based on root element then know we won't need to wrap in an XMLRoot shouldWrap = false; } } } if(xmlDescriptor.hasInheritance()){ //if descriptor has inheritance check class indicator session = xmlContext.getSession(xmlDescriptor); UnmarshalRecord tmpUnmarshalRecord = new UnmarshalRecordImpl(null); tmpUnmarshalRecord.setUnmarshaller(unmarshaller); tmpUnmarshalRecord.setUnmarshalNamespaceResolver(unmarshalNamespaceResolver); tmpUnmarshalRecord.setXMLReader(this.getXMLReader()); tmpUnmarshalRecord.setAttributes(atts); Class classValue = xmlDescriptor.getInheritancePolicy().classFromRow(new org.eclipse.persistence.oxm.record.UnmarshalRecord(tmpUnmarshalRecord), session); if (classValue == null) { // no xsi:type attribute - look for type indicator on the default root element QName leafElementType = xmlDescriptor.getDefaultRootElementType(); // if we have a user-set type, try to get the class from the inheritance policy if (leafElementType != null) { Object indicator = xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(leafElementType); if(indicator != null) { classValue = (Class)indicator; } } } if (classValue != null) { xmlDescriptor = (Descriptor)session.getDescriptor(classValue); } else { // since there is no xsi:type attribute, we'll use the descriptor // that was retrieved based on the rootQName - we need to make // sure it is non-abstract if (Modifier.isAbstract(xmlDescriptor.getJavaClass().getModifiers())) { // need to throw an exception here throw DescriptorException.missingClassIndicatorField((XMLRecord) tmpUnmarshalRecord, (org.eclipse.persistence.oxm.XMLDescriptor)xmlDescriptor.getInheritancePolicy().getDescriptor()); } } } } if (null == xmlDescriptor) { //check for a cached object and look for descriptor by class Object obj = this.xmlReader.getCurrentObject(session, null); if (obj != null) { xmlDescriptor = (Descriptor)xmlContext.getSession(obj.getClass()).getDescriptor(obj.getClass()); } } if (null == xmlDescriptor && primitiveWrapperClass == null){ if(!this.keepAsElementPolicy.isKeepNoneAsElement()) { this.documentBuilder = new SAXDocumentBuilder(); documentBuilder.startDocument(); //start any prefixes that have already been started for(String prefix:this.unmarshalNamespaceResolver.getPrefixes()) { documentBuilder.startPrefixMapping(prefix, this.unmarshalNamespaceResolver.getNamespaceURI(prefix)); } documentBuilder.startElement(namespaceURI, localName, qName, atts); this.xmlReader.setContentHandler(documentBuilder); return; } Class unmappedContentHandlerClass = unmarshaller.getUnmappedContentHandlerClass(); if (null == unmappedContentHandlerClass) { throw XMLMarshalException.noDescriptorWithMatchingRootElement(rootQName.toString()); } else { UnmappedContentHandler unmappedContentHandler; try { PrivilegedNewInstanceFromClass privilegedNewInstanceFromClass = new PrivilegedNewInstanceFromClass(unmappedContentHandlerClass); unmappedContentHandler = (UnmappedContentHandler)privilegedNewInstanceFromClass.run(); } catch (ClassCastException e) { throw XMLMarshalException.unmappedContentHandlerDoesntImplement(e, unmappedContentHandlerClass.getName()); } catch (IllegalAccessException e) { throw XMLMarshalException.errorInstantiatingUnmappedContentHandler(e, unmappedContentHandlerClass.getName()); } catch (InstantiationException e) { throw XMLMarshalException.errorInstantiatingUnmappedContentHandler(e, unmappedContentHandlerClass.getName()); } UnmappedContentHandlerWrapper unmappedContentHandlerWrapper = new UnmappedContentHandlerWrapper(unmappedContentHandler, this); unmappedContentHandler.startElement(namespaceURI, localName, qName, atts); xmlReader.setContentHandler(unmappedContentHandler); setObject(unmappedContentHandlerWrapper.getCurrentObject()); return; } } if (xmlDescriptor == null && primitiveWrapperClass != null) { session = xmlContext.getSession((Descriptor) null); rootRecord = unmarshaller.createRootUnmarshalRecord(primitiveWrapperClass); rootRecord.setSession((CoreAbstractSession) unmarshaller.getContext().getSession()); } else{ if(session == null){ session = xmlContext.getSession(xmlDescriptor); } rootRecord = unmarshaller.createUnmarshalRecord(xmlDescriptor, session); } this.descriptor = xmlDescriptor; rootRecord.setUnmarshaller(this.unmarshaller); rootRecord.setXMLReader(this.getXMLReader()); if (locator != null) { rootRecord.setDocumentLocator(xmlReader.getLocator()); } rootRecord.setAttributes(atts); boolean hasNilAttribute = (atts != null && null != atts.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE)); rootRecord.setNil(isNil || hasNilAttribute); rootRecord.setUnmarshalNamespaceResolver(unmarshalNamespaceResolver); rootRecord.startDocument(); rootRecord.initializeRecord((Mapping) null); xmlReader.setContentHandler(rootRecord); xmlReader.setLexicalHandler(rootRecord); Object attributeGroup = this.unmarshaller.getUnmarshalAttributeGroup(); if(attributeGroup != null) { if(attributeGroup.getClass() == CoreClassConstants.STRING) { CoreAttributeGroup group = descriptor.getAttributeGroup((String)attributeGroup); if(group != null) { rootRecord.setUnmarshalAttributeGroup(group); } else { //Error } } else if(attributeGroup instanceof CoreAttributeGroup) { rootRecord.setUnmarshalAttributeGroup((CoreAttributeGroup)attributeGroup); } else { //Error case } } rootRecord.startElement(namespaceURI, localName, qName, atts); // if we located the descriptor via xsi:type attribute, create and // return an XMLRoot object } catch (EclipseLinkException e) { if (null == xmlReader.getErrorHandler()) { throw e; } else { SAXParseException saxParseException = new SAXParseException(null, null, null, 0, 0, e); xmlReader.getErrorHandler().error(saxParseException); } } } @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException { } @Override public void characters(char[] ch, int start, int length) throws SAXException { } @Override public void characters(CharSequence characters) throws SAXException { } @Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { } @Override public void processingInstruction(String target, String data) throws SAXException { } @Override public void skippedEntity(String name) throws SAXException { } public void setUnmarshaller(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } public Unmarshaller getUnmarshaller() { return this.unmarshaller; } public void setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy policy) { this.keepAsElementPolicy = policy; } public UnmarshalKeepAsElementPolicy getKeepAsElementPolicy() { return this.keepAsElementPolicy; } @Override public void setNil(boolean isNil) { this.isNil = isNil; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy