| /* |
| * Copyright (c) 1998, 2019 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; |
| } |
| } |