org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.persistence.core Show documentation
Show all versions of org.eclipse.persistence.core Show documentation
EclipseLink build based upon Git transaction ecdf3c32c4
/*
* 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.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
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.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.ValidatorHandler;
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.helper.XMLHelper;
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.MediaType;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.Unmarshaller;
import org.eclipse.persistence.internal.oxm.UnmarshallerHandler;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.internal.oxm.record.json.JsonStructureReader;
import org.eclipse.persistence.platform.xml.DefaultErrorHandler;
import org.eclipse.persistence.platform.xml.SAXDocumentBuilder;
import org.eclipse.persistence.platform.xml.XMLParser;
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.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* INTERNAL:
* Purpose:Provide an implementation of PlatformUnmarshaller that makes use of the SAX parser
* to build Java Objects from SAX Events.
*
Responsibilities:
* - Implement the required unmarshal methods from PlatformUnmarshaller
* - Check to see if document preservation is enabled, and if so, always unmarshal from a node
*
*
* @author bdoughan
* @see org.eclipse.persistence.oxm.platform.SAXPlatform
*/
public class SAXUnmarshaller implements PlatformUnmarshaller {
private static final String VALIDATING = "http://xml.org/sax/features/validation";
private static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
private static final String SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
private static final String XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
private static final UnmarshalKeepAsElementPolicy KEEP_UNKNOWN_AS_ELEMENT = new UnmarshalKeepAsElementPolicy() {
@Override
public boolean isKeepAllAsElement() {
return false;
}
@Override
public boolean isKeepNoneAsElement() {
return false;
}
@Override
public boolean isKeepUnknownAsElement() {
return true;
}
};
private int validationMode = XMLParser.NONVALIDATING;
private Schema schema;
private Object[] schemas;
private EntityResolver entityResolver;
private ErrorHandler errorHandler = DefaultErrorHandler.getInstance();
private SAXParser saxParser;
private XMLReader xmlReader;
private Unmarshaller xmlUnmarshaller;
private XMLParser xmlParser;
private boolean isResultAlwaysXMLRoot, isWhitespacePreserving;
private SAXParserFactory saxParserFactory;
private String systemId = null;
private Map parserFeatures;
private boolean disableSecureProcessing = false;
private boolean shouldReset = true;
private XMLPlatform xmlPLatform;
public SAXUnmarshaller(Unmarshaller xmlUnmarshaller, Map parserFeatures) throws XMLMarshalException {
super();
this.parserFeatures = parserFeatures;
try {
this.xmlUnmarshaller = xmlUnmarshaller;
} catch (Exception e) {
throw XMLMarshalException.errorInstantiatingSchemaPlatform(e);
}
}
private SAXParserFactory getSAXParserFactory() throws XMLMarshalException {
if (null == saxParserFactory || shouldReset) {
try {
saxParserFactory = XMLHelper.createParserFactory(isSecureProcessingDisabled());;
saxParserFactory.setFeature(XMLReader.NAMESPACE_PREFIXES_FEATURE, true);
try {
saxParserFactory.setFeature(XMLReader.REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE_FEATURE, true);
} catch (org.xml.sax.SAXNotRecognizedException ex) {
// ignore if the parser doesn't recognize or support this feature
} catch (org.xml.sax.SAXNotSupportedException ex) {
}
if (null != parserFeatures) {
for (Map.Entry parserFeature : parserFeatures.entrySet()) {
try {
saxParserFactory.setFeature(parserFeature.getKey(), parserFeature.getValue());
} catch (org.xml.sax.SAXNotRecognizedException ex) {
// ignore if the parser doesn't recognize or support this feature
} catch (org.xml.sax.SAXNotSupportedException ex) {
}
}
}
return saxParserFactory;
} catch (Exception e) {
throw XMLMarshalException.errorInstantiatingSchemaPlatform(e);
}
}
return saxParserFactory;
}
private SAXParser getSAXParser() {
if (null == saxParser) {
try {
saxParser = getSAXParserFactory().newSAXParser();
} catch (Exception e) {
throw XMLMarshalException.errorInstantiatingSchemaPlatform(e);
}
}
return saxParser;
}
private XMLParser getXMLParser() {
if (xmlParser == null || shouldReset) {
XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
xmlPlatform.setDisableSecureProcessing(isSecureProcessingDisabled());
xmlParser = xmlPlatform.newXMLParser();
xmlParser.setNamespaceAware(true);
if (null != errorHandler) {
xmlParser.setErrorHandler(errorHandler);
}
if (null != entityResolver) {
xmlParser.setEntityResolver(entityResolver);
}
xmlParser.setValidationMode(validationMode);
xmlParser.setWhitespacePreserving(isWhitespacePreserving);
shouldReset = false;
}
return xmlParser;
}
private XMLReader getXMLReader() {
return getXMLReader(null);
}
private XMLReader getXMLReader(Class clazz) {
if (null == xmlReader) {
xmlReader = getNewXMLReader(clazz, xmlUnmarshaller.getMediaType());
}
return xmlReader;
}
private XMLReader getNewXMLReader(MediaType mediaType) {
return getNewXMLReader(null, mediaType);
}
private XMLReader getNewXMLReader(Class clazz, MediaType mediaType) {
if (null != mediaType && mediaType.isApplicationJSON()) {
return new JsonStructureReader(xmlUnmarshaller, clazz);
}
try {
XMLReader xmlReader = new XMLReader(getSAXParser().getXMLReader());
if (null != errorHandler) {
xmlReader.setErrorHandler(errorHandler);
}
if (null != entityResolver) {
xmlReader.setEntityResolver(entityResolver);
}
setValidationMode(xmlReader, getValidationMode());
if (null != getSchema()) {
xmlReader.setFeature(VALIDATING, xmlReader.getFeature(VALIDATING));
}
return xmlReader;
} catch (Exception e) {
throw XMLMarshalException.errorInstantiatingSchemaPlatform(e);
}
}
@Override
public EntityResolver getEntityResolver() {
return entityResolver;
}
@Override
public void setEntityResolver(EntityResolver entityResolver) {
if (null != xmlReader) {
xmlReader.setEntityResolver(entityResolver);
}
if (null != xmlParser) {
xmlParser.setEntityResolver(entityResolver);
}
this.entityResolver = entityResolver;
}
@Override
public ErrorHandler getErrorHandler() {
return errorHandler;
}
@Override
public void setErrorHandler(ErrorHandler errorHandler) {
if (null != xmlReader) {
xmlReader.setErrorHandler(errorHandler);
}
if (null != xmlParser) {
xmlParser.setErrorHandler(errorHandler);
}
this.errorHandler = errorHandler;
}
@Override
public int getValidationMode() {
return validationMode;
}
@Override
public void setValidationMode(int validationMode) {
setValidationMode(xmlReader, validationMode);
}
public void setValidationMode(XMLReader xmlReader, int validationMode) {
try {
this.validationMode = validationMode;
if (null != xmlParser) {
xmlParser.setValidationMode(validationMode);
}
if (null == xmlReader) {
return;
}
switch (validationMode) {
case XMLParser.NONVALIDATING: {
xmlReader.setFeature(VALIDATING, false);
break;
}
case XMLParser.DTD_VALIDATION: {
xmlReader.setFeature(VALIDATING, true);
XMLHelper.allowExternalDTDAccess(xmlReader, "all", false);
break;
}
case XMLParser.SCHEMA_VALIDATION: {
try {
xmlReader.setFeature(VALIDATING, true);
XMLHelper.allowExternalAccess(xmlReader, "all", false);
saxParser.setProperty(SCHEMA_LANGUAGE, XML_SCHEMA);
saxParser.setProperty(SCHEMA_SOURCE, schemas);
} catch (Exception e) {
xmlReader.setFeature(VALIDATING, false);
}
break;
}
}
} catch (Exception e) {
// Don't change the validation mode.
}
}
@Override
public void setWhitespacePreserving(boolean isWhitespacePreserving) {
this.isWhitespacePreserving = isWhitespacePreserving;
if (null != xmlParser) {
xmlParser.setWhitespacePreserving(isWhitespacePreserving);
}
}
@Override
public void setSchemas(Object[] schemas) {
this.schemas = schemas;
}
@Override
public void setSchema(Schema schema) {
this.schema = schema;
if (null != xmlParser) {
xmlParser.setXMLSchema(schema);
}
}
@Override
public Schema getSchema() {
return schema;
}
@Override
public Object unmarshal(File file) {
try {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(file).getDocumentElement();
return unmarshal(domElement);
}
this.systemId = file.toURI().toURL().toExternalForm();
FileInputStream inputStream = new FileInputStream(file);
try {
return unmarshal(inputStream);
} finally {
inputStream.close();
}
} catch (FileNotFoundException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(File file, Class clazz) {
try {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(file).getDocumentElement();
return unmarshal(domElement, clazz);
}
this.systemId = file.toURI().toURL().toExternalForm();
FileInputStream inputStream = new FileInputStream(file);
try {
return unmarshal(inputStream, clazz);
} finally {
inputStream.close();
}
} catch (FileNotFoundException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(InputStream inputStream) {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(inputStream).getDocumentElement();
return unmarshal(domElement);
}
InputSource inputSource = new InputSource(inputStream);
return unmarshal(inputSource);
}
@Override
public Object unmarshal(InputStream inputStream, Class clazz) {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(inputStream).getDocumentElement();
return unmarshal(domElement, clazz);
}
InputSource inputSource = new InputSource(inputStream);
return unmarshal(inputSource, clazz);
}
@Override
public Object unmarshal(InputSource inputSource) {
if (inputSource != null && null == inputSource.getSystemId()) {
inputSource.setSystemId(this.systemId);
}
if (xmlUnmarshaller.isAutoDetectMediaType()) {
BufferedReader bufferedReader = getBufferedReaderForInputSource(inputSource);
MediaType mediaType = getMediaType(bufferedReader);
return unmarshal(getNewXMLReader(mediaType), new InputSource(bufferedReader));
}
return unmarshal(getXMLReader(), inputSource);
}
public Object unmarshal(InputSource inputSource, XMLReader xmlReader) {
try {
if (inputSource != null && null == inputSource.getSystemId()) {
inputSource.setSystemId(this.systemId);
}
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
saxUnmarshallerHandler.setXMLReader(xmlReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
setContentHandler(xmlReader, saxUnmarshallerHandler);
xmlReader.parse(inputSource);
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(InputSource inputSource, Class clazz) {
if (inputSource != null && null == inputSource.getSystemId()) {
inputSource.setSystemId(this.systemId);
}
if (xmlUnmarshaller.isAutoDetectMediaType()) {
BufferedReader bufferedReader = getBufferedReaderForInputSource(inputSource);
MediaType mediaType = getMediaType(bufferedReader);
return unmarshal(getNewXMLReader(clazz, mediaType), new InputSource(bufferedReader), clazz);
}
return unmarshal(getXMLReader(clazz), inputSource, clazz);
}
public Object unmarshal(InputSource inputSource, Class clazz, XMLReader xmlReader) {
if (inputSource != null && null == inputSource.getSystemId()) {
inputSource.setSystemId(this.systemId);
}
UnmarshalRecord unmarshalRecord = null;
Descriptor xmlDescriptor = null;
// for XMLObjectReferenceMappings we need a non-shared cache, so
// try and get a Unit Of Work from the XMLContext
CoreAbstractSession session = null;
// check for case where the reference class is a primitive wrapper - in this case, we
// need to use the conversion manager to convert the node's value to the primitive
// wrapper class, then create, populate and return an XMLRoot. This will be done
// via XMLRootRecord.
boolean isPrimitiveWrapper = false;
if (clazz == CoreClassConstants.OBJECT) {
try {
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
saxUnmarshallerHandler.setXMLReader(xmlReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
saxUnmarshallerHandler.setKeepAsElementPolicy(KEEP_UNKNOWN_AS_ELEMENT);
setContentHandler(xmlReader, saxUnmarshallerHandler);
xmlReader.parse(inputSource);
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
}
} else {
// for XMLObjectReferenceMappings we need a non-shared cache, so
// try and get a Unit Of Work from the XMLContext
try {
session = xmlUnmarshaller.getContext().getSession(clazz);
xmlDescriptor = (Descriptor) session.getDescriptor(clazz);
unmarshalRecord = xmlUnmarshaller.createUnmarshalRecord(xmlDescriptor, session);
} catch (XMLMarshalException xme) {
if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
isPrimitiveWrapper = isPrimitiveWrapper(clazz);
if (isPrimitiveWrapper) {
unmarshalRecord = xmlUnmarshaller.createRootUnmarshalRecord(clazz);
} else {
throw xme;
}
} else {
throw xme;
}
}
}
try {
unmarshalRecord.setXMLReader(xmlReader);
unmarshalRecord.setUnmarshaller(xmlUnmarshaller);
setContentHandler(xmlReader, unmarshalRecord);
xmlReader.setLexicalHandler(unmarshalRecord);
xmlReader.parse(inputSource);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
// resolve mapping references
unmarshalRecord.resolveReferences(session, xmlUnmarshaller.getIDResolver());
if (isPrimitiveWrapper) {
return unmarshalRecord.getCurrentObject();
}
return xmlDescriptor.wrapObjectInXMLRoot(unmarshalRecord, this.isResultAlwaysXMLRoot);
}
@Override
public Object unmarshal(Node node) {
DOMReader reader = new DOMReader(xmlUnmarshaller);
return unmarshal(reader, node);
}
public Object unmarshal(DOMReader reader, Node node) {
try {
SAXUnmarshallerHandler handler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
setContentHandler(reader, handler);
handler.setXMLReader(reader);
handler.setUnmarshaller(xmlUnmarshaller);
reader.parse(node);
handler.resolveReferences();
return handler.getObject();
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(Node node, Class clazz) {
DOMReader reader = new DOMReader(xmlUnmarshaller);
return unmarshal(reader, node, clazz);
}
public Object unmarshal(DOMReader domReader, Node node, Class clazz) {
UnmarshalRecord unmarshalRecord = null;
Descriptor xmlDescriptor = null;
CoreAbstractSession session = null;
// check for case where the reference class is a primitive wrapper - in this case, we
// need to use the conversion manager to convert the node's value to the primitive
// wrapper class, then create, populate and return an XMLRoot. This will be done
// via XMLRootRecord.
boolean isPrimitiveWrapper = false;
if (clazz == CoreClassConstants.OBJECT) {
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
saxUnmarshallerHandler.setXMLReader(domReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
saxUnmarshallerHandler.setKeepAsElementPolicy(KEEP_UNKNOWN_AS_ELEMENT);
setContentHandler(domReader, saxUnmarshallerHandler);
try {
domReader.parse(node);
} catch (SAXException e) {
throw convertSAXException(e);
}
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} else {
// for XMLObjectReferenceMappings we need a non-shared cache, so
// try and get a Unit Of Work from the XMLContext
try {
session = xmlUnmarshaller.getContext().getSession(clazz);
xmlDescriptor = (Descriptor) session.getDescriptor(clazz);
unmarshalRecord = xmlUnmarshaller.createUnmarshalRecord(xmlDescriptor, session);
} catch (XMLMarshalException xme) {
if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
isPrimitiveWrapper = isPrimitiveWrapper(clazz);
if (isPrimitiveWrapper) {
unmarshalRecord = xmlUnmarshaller.createRootUnmarshalRecord(clazz);
} else if (Node.class.isAssignableFrom(clazz)) {
return createXMLRootForNode(node);
} else {
throw xme;
}
} else {
throw xme;
}
}
}
try {
unmarshalRecord.setXMLReader(domReader);
unmarshalRecord.setUnmarshaller(xmlUnmarshaller);
setContentHandler(domReader, unmarshalRecord);
domReader.setLexicalHandler(unmarshalRecord);
domReader.parse(node);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
// resolve mapping references
unmarshalRecord.resolveReferences(session, xmlUnmarshaller.getIDResolver());
if (isPrimitiveWrapper) {
return unmarshalRecord.getCurrentObject();
}
return xmlDescriptor.wrapObjectInXMLRoot(unmarshalRecord, this.isResultAlwaysXMLRoot);
}
private Object createXMLRootForNode(Node node) {
Root xmlRoot = xmlUnmarshaller.createRoot();
xmlRoot.setObject(node);
if (node != null) {
xmlRoot.setLocalName(node.getLocalName());
xmlRoot.setNamespaceURI(node.getNamespaceURI());
}
return xmlRoot;
}
@Override
public Object unmarshal(Reader reader) {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(reader).getDocumentElement();
return unmarshal(domElement);
}
InputSource inputSource = new InputSource(reader);
return unmarshal(inputSource);
}
@Override
public Object unmarshal(Reader reader, Class clazz) {
if (xmlUnmarshaller.getContext().hasDocumentPreservation()) {
Node domElement = getXMLParser().parse(reader).getDocumentElement();
return unmarshal(domElement, clazz);
}
InputSource inputSource = new InputSource(reader);
return unmarshal(inputSource, clazz);
}
@Override
public Object unmarshal(Source source) {
try {
if (source instanceof SAXSource) {
SAXSource saxSource = (SAXSource) source;
XMLReader xmlReader = null;
if (saxSource.getXMLReader() != null) {
if (saxSource.getXMLReader() instanceof XMLReader) {
xmlReader = (XMLReader) saxSource.getXMLReader();
} else {
xmlReader = new XMLReader(saxSource.getXMLReader());
}
setValidatorHandler(xmlReader);
}
if (null == xmlReader) {
return unmarshal(saxSource.getInputSource());
} else {
return unmarshal(saxSource.getInputSource(), xmlReader);
}
} else if (source instanceof DOMSource) {
DOMSource domSource = (DOMSource) source;
return unmarshal(domSource.getNode());
} else if (source instanceof StreamSource) {
StreamSource streamSource = (StreamSource) source;
if (null != streamSource.getReader()) {
return unmarshal(streamSource.getReader());
} else if (null != streamSource.getInputStream()) {
return unmarshal(streamSource.getInputStream());
} else {
return unmarshal(streamSource.getSystemId());
}
} else if (source instanceof ExtendedSource) {
ExtendedSource extendedSource = (ExtendedSource) source;
return unmarshal(null, extendedSource.createReader(xmlUnmarshaller));
} else {
UnmarshallerHandler handler = this.xmlUnmarshaller.getUnmarshallerHandler();
XMLPlatform xmlPlat = XMLPlatformFactory.getInstance().getXMLPlatform();
xmlPlat.setDisableSecureProcessing(isSecureProcessingDisabled());
XMLTransformer transformer = xmlPLatform.newXMLTransformer();
SAXResult result = new SAXResult(handler);
transformer.transform(source, result);
return handler.getResult();
}
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(Source source, Class clazz) {
if (source instanceof SAXSource) {
SAXSource saxSource = (SAXSource) source;
XMLReader xmlReader = null;
if (saxSource.getXMLReader() != null) {
if (saxSource.getXMLReader() instanceof XMLReader) {
xmlReader = (XMLReader) saxSource.getXMLReader();
} else {
xmlReader = new XMLReader(saxSource.getXMLReader());
}
setValidatorHandler(xmlReader);
}
if (null == saxSource.getXMLReader()) {
return unmarshal(saxSource.getInputSource(), clazz);
} else {
return unmarshal(saxSource.getInputSource(), clazz, xmlReader);
}
} else if (source instanceof DOMSource) {
DOMSource domSource = (DOMSource) source;
return unmarshal(domSource.getNode(), clazz);
} else if (source instanceof StreamSource) {
StreamSource streamSource = (StreamSource) source;
if (null != streamSource.getReader()) {
return unmarshal(streamSource.getReader(), clazz);
} else if (null != streamSource.getInputStream()) {
return unmarshal(streamSource.getInputStream(), clazz);
} else {
return unmarshal(streamSource.getSystemId(), clazz);
}
} else if (source instanceof ExtendedSource) {
ExtendedSource extendedSource = (ExtendedSource) source;
return unmarshal(null, clazz, extendedSource.createReader(xmlUnmarshaller, clazz));
} else {
DOMResult result = new DOMResult();
XMLPlatform xmlPlat = XMLPlatformFactory.getInstance().getXMLPlatform();
xmlPlat.setDisableSecureProcessing(isSecureProcessingDisabled());
XMLTransformer transformer = xmlPLatform.newXMLTransformer();
transformer.transform(source, result);
return unmarshal(result.getNode(), clazz);
}
}
@Override
public Object unmarshal(URL url) {
InputStream inputStream = null;
try {
inputStream = url.openStream();
} catch (Exception e) {
throw XMLMarshalException.unmarshalException(e);
}
this.systemId = url.toExternalForm();
boolean hasThrownException = false;
try {
return unmarshal(inputStream);
} catch (RuntimeException runtimeException) {
hasThrownException = true;
throw runtimeException;
} finally {
xmlUnmarshaller.getStringBuffer().reset();
try {
inputStream.close();
} catch (IOException e) {
if (!hasThrownException) {
throw XMLMarshalException.unmarshalException(e);
}
}
}
}
@Override
public Object unmarshal(URL url, Class clazz) {
InputStream inputStream = null;
try {
inputStream = url.openStream();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
}
this.systemId = url.toExternalForm();
try {
return unmarshal(inputStream, clazz);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
try {
inputStream.close();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
}
}
}
public Object unmarshal(String systemId) {
try {
if (xmlUnmarshaller.isAutoDetectMediaType()) {
InputSource inputSource = new InputSource(systemId);
return unmarshal(inputSource);
}
XMLReader xmlReader = getXMLReader();
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
saxUnmarshallerHandler.setXMLReader(xmlReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
setContentHandler(xmlReader, saxUnmarshallerHandler);
xmlReader.parse(systemId);
// resolve mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
public Object unmarshal(String systemId, Class clazz) {
if (xmlUnmarshaller.isAutoDetectMediaType()) {
return unmarshal(new InputSource(systemId), clazz);
}
UnmarshalRecord unmarshalRecord = null;
boolean isPrimitiveWrapper = false;
Descriptor xmlDescriptor = null;
CoreAbstractSession session = null;
// check for case where the reference class is a primitive wrapper - in this case, we
// need to use the conversion manager to convert the node's value to the primitive
// wrapper class, then create, populate and return an XMLRoot. This will be done
// via XMLRootRecord.
if (clazz == CoreClassConstants.OBJECT) {
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
try {
XMLReader xmlReader = getXMLReader(clazz);
saxUnmarshallerHandler.setXMLReader(xmlReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
saxUnmarshallerHandler.setKeepAsElementPolicy(KEEP_UNKNOWN_AS_ELEMENT);
setContentHandler(xmlReader, saxUnmarshallerHandler);
xmlReader.parse(systemId);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} else {
// for XMLObjectReferenceMappings we need a non-shared cache, so
// try and get a Unit Of Work from the XMLContext
try {
session = xmlUnmarshaller.getContext().getSession(clazz);
xmlDescriptor = (Descriptor) session.getDescriptor(clazz);
unmarshalRecord = xmlUnmarshaller.createUnmarshalRecord(xmlDescriptor, session);
} catch (XMLMarshalException xme) {
if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
isPrimitiveWrapper = isPrimitiveWrapper(clazz);
if (isPrimitiveWrapper) {
unmarshalRecord = xmlUnmarshaller.createRootUnmarshalRecord(clazz);
} else {
throw xme;
}
} else {
throw xme;
}
}
}
try {
XMLReader xmlReader = getXMLReader(clazz);
unmarshalRecord.setXMLReader(xmlReader);
unmarshalRecord.setUnmarshaller(xmlUnmarshaller);
setContentHandler(xmlReader, unmarshalRecord);
xmlReader.setLexicalHandler(unmarshalRecord);
xmlReader.parse(systemId);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
// resolve mapping references
unmarshalRecord.resolveReferences(session, xmlUnmarshaller.getIDResolver());
if (isPrimitiveWrapper) {
return unmarshalRecord.getCurrentObject();
}
return xmlDescriptor.wrapObjectInXMLRoot(unmarshalRecord, this.isResultAlwaysXMLRoot);
}
@Override
public Object unmarshal(org.xml.sax.XMLReader xmlReader, InputSource inputSource) {
try {
Context xmlContext = xmlUnmarshaller.getContext();
if (xmlContext.hasDocumentPreservation()) {
SAXDocumentBuilder saxDocumentBuilder = new SAXDocumentBuilder();
xmlReader.setContentHandler(saxDocumentBuilder);
xmlReader.parse(inputSource);
return unmarshal(saxDocumentBuilder.getDocument().getDocumentElement());
}
XMLReader extendedXMLReader;
if (xmlReader instanceof XMLReader) {
extendedXMLReader = (XMLReader) xmlReader;
} else {
extendedXMLReader = new XMLReader(xmlReader);
}
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlContext);
saxUnmarshallerHandler.setXMLReader(extendedXMLReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
setContentHandler(extendedXMLReader, saxUnmarshallerHandler);
extendedXMLReader.parse(inputSource);
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
@Override
public Object unmarshal(org.xml.sax.XMLReader xmlReader, InputSource inputSource, Class clazz) {
try {
Context xmlContext = xmlUnmarshaller.getContext();
if (xmlContext.hasDocumentPreservation() || (Node.class.isAssignableFrom(clazz) && xmlUnmarshaller.isApplicationXML())) {
SAXDocumentBuilder saxDocumentBuilder = new SAXDocumentBuilder();
xmlReader.setContentHandler(saxDocumentBuilder);
xmlReader.parse(inputSource);
return unmarshal(saxDocumentBuilder.getDocument().getDocumentElement(), clazz);
}
UnmarshalRecord unmarshalRecord = null;
Descriptor xmlDescriptor = null;
CoreAbstractSession session = null;
boolean isPrimitiveWrapper = false;
// check for case where the reference class is a primitive wrapper - in this case, we
// need to use the conversion manager to convert the node's value to the primitive
// wrapper class, then create, populate and return an XMLRoot. This will be done
// via XMLRootRecord.
if (clazz == CoreClassConstants.OBJECT) {
SAXUnmarshallerHandler saxUnmarshallerHandler = new SAXUnmarshallerHandler(xmlUnmarshaller.getContext());
saxUnmarshallerHandler.setXMLReader((XMLReader) xmlReader);
saxUnmarshallerHandler.setUnmarshaller(xmlUnmarshaller);
saxUnmarshallerHandler.setKeepAsElementPolicy(KEEP_UNKNOWN_AS_ELEMENT);
xmlReader.setContentHandler(saxUnmarshallerHandler);
xmlReader.parse(inputSource);
// resolve any mapping references
saxUnmarshallerHandler.resolveReferences();
return saxUnmarshallerHandler.getObject();
} else {
// for XMLObjectReferenceMappings we need a non-shared cache, so
// try and get a Unit Of Work from the XMLContext
try {
session = xmlContext.getSession(clazz);
xmlDescriptor = (Descriptor) session.getDescriptor(clazz);
unmarshalRecord = xmlUnmarshaller.createUnmarshalRecord(xmlDescriptor, session);
} catch (XMLMarshalException xme) {
if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
isPrimitiveWrapper = isPrimitiveWrapper(clazz);
if (isPrimitiveWrapper) {
unmarshalRecord = xmlUnmarshaller.createRootUnmarshalRecord(clazz);
} else {
throw xme;
}
} else {
throw xme;
}
}
}
XMLReader extendedXMLReader;
if (xmlReader instanceof XMLReader) {
extendedXMLReader = (XMLReader) xmlReader;
} else {
extendedXMLReader = new XMLReader(xmlReader);
}
unmarshalRecord.setXMLReader(extendedXMLReader);
unmarshalRecord.setUnmarshaller(xmlUnmarshaller);
setContentHandler(extendedXMLReader, unmarshalRecord);
extendedXMLReader.setLexicalHandler(unmarshalRecord);
extendedXMLReader.parse(inputSource);
// resolve mapping references
unmarshalRecord.resolveReferences(session, xmlUnmarshaller.getIDResolver());
if (isPrimitiveWrapper || clazz == CoreClassConstants.OBJECT) {
return unmarshalRecord.getCurrentObject();
}
return xmlDescriptor.wrapObjectInXMLRoot(unmarshalRecord, this.isResultAlwaysXMLRoot);
} catch (IOException e) {
throw XMLMarshalException.unmarshalException(e);
} catch (SAXException e) {
throw convertSAXException(e);
} finally {
xmlUnmarshaller.getStringBuffer().reset();
}
}
private EclipseLinkException convertSAXException(SAXException saxException) {
Exception internalException = saxException.getException();
if (internalException != null) {
if (EclipseLinkException.class.isAssignableFrom(internalException.getClass())) {
return (EclipseLinkException) internalException;
} else {
return XMLMarshalException.unmarshalException(internalException);
}
}
return XMLMarshalException.unmarshalException(saxException);
}
@Override
public boolean isResultAlwaysXMLRoot() {
return this.isResultAlwaysXMLRoot;
}
@Override
public void setResultAlwaysXMLRoot(boolean alwaysReturnRoot) {
this.isResultAlwaysXMLRoot = alwaysReturnRoot;
}
private boolean isPrimitiveWrapper(Class clazz) {
return ((ConversionManager) xmlUnmarshaller.getContext().getSession().getDatasourcePlatform().getConversionManager()).schemaType(clazz) != null
|| CoreClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(clazz)
|| CoreClassConstants.DURATION.isAssignableFrom(clazz);
}
/**
* If a Schema was set on the unmarshaller then wrap the ContentHandler in
* a ValidatorHandler.
*/
private void setContentHandler(XMLReader xmlReader, ContentHandler contentHandler) {
setValidatorHandler(xmlReader);
xmlReader.setContentHandler(contentHandler);
}
private void setValidatorHandler(XMLReader xmlReader) {
Schema schema = getSchema();
if (null != schema) {
ValidatorHandler validatorHandler = schema.newValidatorHandler();
xmlReader.setValidatorHandler(validatorHandler);
validatorHandler.setErrorHandler(getErrorHandler());
}
}
@Override
public void mediaTypeChanged() {
xmlReader = null;
}
private InputStream getInputStreamFromString(String stringValue) {
if (stringValue.length() == 0) {
throw org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalFromStringException(stringValue, null);
}
URL url = null;
try {
url = new URL(stringValue);
if (url != null) {
try {
return url.openStream();
} catch (IOException e) {
throw org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalFromStringException(stringValue, e);
}
}
} catch (MalformedURLException ex) {
try {
return new FileInputStream(stringValue);
} catch (FileNotFoundException e) {
throw org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalFromStringException(stringValue, e);
}
}
throw org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalFromStringException(stringValue, null);
}
private BufferedReader getBufferedReaderForInputSource(InputSource inputSource) {
if (inputSource.getByteStream() != null) {
return new BufferedReader(new InputStreamReader(inputSource.getByteStream()));
} else if (inputSource.getCharacterStream() != null) {
return new BufferedReader(inputSource.getCharacterStream());
} else if (inputSource.getSystemId() != null) {
InputStream is = getInputStreamFromString(inputSource.getSystemId());
return new BufferedReader(new InputStreamReader(is));
}
throw XMLMarshalException.unmarshalException();
}
private MediaType getMediaType(BufferedReader br) {
int READ_AHEAD_LIMIT = 25;
try {
br.mark(READ_AHEAD_LIMIT);
try {
char c = 0;
for (int i = 0; c != -1 && i < READ_AHEAD_LIMIT; i++) {
c = (char) br.read();
if (c == '[' || c == '{') {
return Constants.APPLICATION_JSON;
} else if (c == '<') {
return Constants.APPLICATION_XML;
}
}
} finally {
br.reset();
}
} catch (IOException ioException) {
throw XMLMarshalException.unmarshalException(ioException);
}
return xmlUnmarshaller.getMediaType();
}
@Override
public final boolean isSecureProcessingDisabled() {
return disableSecureProcessing;
}
@Override
public final void setDisableSecureProcessing(boolean disableSecureProcessing) {
shouldReset = this.disableSecureProcessing ^ disableSecureProcessing;
this.disableSecureProcessing = disableSecureProcessing;
}
}