/*
 * Copyright (c) 1998, 2021 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:
 * <p><b>Purpose:</b>Provide an implementation of PlatformUnmarshaller that makes use of the SAX parser
 * to build Java Objects from SAX Events.
 * <p><b>Responsibilities:</b><ul>
 * <li>Implement the required unmarshal methods from PlatformUnmarshaller</li>
 * <li>Check to see if document preservation is enabled, and if so, always unmarshal from a node</li>
 * </ul>
 *
 * @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<String, Boolean> parserFeatures;
    private boolean disableSecureProcessing = false;
    private boolean shouldReset = true;
    private XMLPlatform xmlPLatform;

    public SAXUnmarshaller(Unmarshaller xmlUnmarshaller, Map<String, Boolean> 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<String, Boolean> 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;
    }
}
