/******************************************************************************* | |
* Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved. | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* 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.oxm.Constants; | |
import org.eclipse.persistence.internal.oxm.Context; | |
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.XMLConversionManager; | |
import org.eclipse.persistence.internal.oxm.mappings.Descriptor; | |
import org.eclipse.persistence.internal.oxm.mappings.UnmarshalKeepAsElementPolicy; | |
import org.eclipse.persistence.internal.oxm.record.json.JSONReader; | |
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.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 = new DefaultErrorHandler(); | |
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; | |
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) { | |
try { | |
saxParserFactory = SAXParserFactory.newInstance(); | |
saxParserFactory.setNamespaceAware(true); | |
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() { | |
xmlParser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser(); | |
xmlParser.setNamespaceAware(true); | |
if(null != errorHandler) { | |
xmlParser.setErrorHandler(errorHandler); | |
} | |
if(null != entityResolver) { | |
xmlParser.setEntityResolver(entityResolver); | |
} | |
xmlParser.setValidationMode(validationMode); | |
xmlParser.setWhitespacePreserving(isWhitespacePreserving); | |
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(mediaType.isApplicationJSON()){ | |
return new JSONReader(xmlUnmarshaller.getAttributePrefix(), xmlUnmarshaller.getNamespaceResolver(), xmlUnmarshaller.getNamespaceResolver() != null, xmlUnmarshaller.isIncludeRoot(), xmlUnmarshaller.getNamespaceSeparator(), xmlUnmarshaller.getErrorHandler(), xmlUnmarshaller.getValueWrapper(), 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); | |
} | |
} | |
public EntityResolver getEntityResolver() { | |
return entityResolver; | |
} | |
public void setEntityResolver(EntityResolver entityResolver) { | |
if(null != xmlReader) { | |
xmlReader.setEntityResolver(entityResolver); | |
} | |
if(null != xmlParser) { | |
xmlParser.setEntityResolver(entityResolver); | |
} | |
this.entityResolver = entityResolver; | |
} | |
public ErrorHandler getErrorHandler() { | |
return errorHandler; | |
} | |
public void setErrorHandler(ErrorHandler errorHandler) { | |
if(null != xmlReader) { | |
xmlReader.setErrorHandler(errorHandler); | |
} | |
if(null != xmlParser) { | |
xmlParser.setErrorHandler(errorHandler); | |
} | |
this.errorHandler = errorHandler; | |
} | |
public int getValidationMode() { | |
return validationMode; | |
} | |
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); | |
break; | |
} | |
case XMLParser.SCHEMA_VALIDATION: { | |
try { | |
xmlReader.setFeature(VALIDATING, true); | |
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. | |
} | |
} | |
public void setWhitespacePreserving(boolean isWhitespacePreserving) { | |
this.isWhitespacePreserving = isWhitespacePreserving; | |
if(null != xmlParser) { | |
xmlParser.setWhitespacePreserving(isWhitespacePreserving); | |
} | |
} | |
public void setSchemas(Object[] schemas) { | |
this.schemas = schemas; | |
} | |
public void setSchema(Schema schema) { | |
this.schema = schema; | |
if(null != xmlParser) { | |
xmlParser.setXMLSchema(schema); | |
} | |
} | |
public Schema getSchema() { | |
return schema; | |
} | |
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(); | |
} | |
} | |
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(); | |
} | |
} | |
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); | |
} | |
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); | |
} | |
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(); | |
} | |
} | |
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); | |
} | |
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(); | |
} | |
} | |
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; | |
} | |
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); | |
} | |
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); | |
} | |
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 { | |
UnmarshallerHandler handler = this.xmlUnmarshaller.getUnmarshallerHandler(); | |
XMLTransformer transformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer(); | |
SAXResult result = new SAXResult(handler); | |
transformer.transform(source, result); | |
return handler.getResult(); | |
} | |
}finally { | |
xmlUnmarshaller.getStringBuffer().reset(); | |
} | |
} | |
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 { | |
DOMResult result = new DOMResult(); | |
XMLTransformer transformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer(); | |
transformer.transform(source, result); | |
return unmarshal(result.getNode(), clazz); | |
} | |
} | |
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); | |
} | |
} | |
} | |
} | |
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); | |
} | |
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(); | |
} | |
} | |
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.getMediaType().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); | |
} | |
public boolean isResultAlwaysXMLRoot() { | |
return this.isResultAlwaysXMLRoot; | |
} | |
public void setResultAlwaysXMLRoot(boolean alwaysReturnRoot) { | |
this.isResultAlwaysXMLRoot = alwaysReturnRoot; | |
} | |
private boolean isPrimitiveWrapper(Class clazz){ | |
return XMLConversionManager.getDefaultJavaTypes().get(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(); | |
} | |
} |