| /* |
| * 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.sdo.helper.delegates; |
| |
| import commonj.sdo.DataObject; |
| import commonj.sdo.Property; |
| import commonj.sdo.helper.HelperContext; |
| import commonj.sdo.helper.XMLDocument; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TimeZone; |
| import java.util.WeakHashMap; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.transform.Result; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.dom.DOMResult; |
| import javax.xml.transform.sax.SAXResult; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.eclipse.persistence.sdo.SDOConstants; |
| import org.eclipse.persistence.sdo.SDOType; |
| import org.eclipse.persistence.sdo.SDOXMLDocument; |
| import org.eclipse.persistence.sdo.helper.SDOUnmappedContentHandler; |
| import org.eclipse.persistence.sdo.helper.SDOClassLoader; |
| import org.eclipse.persistence.sdo.helper.SDOMarshalListener; |
| import org.eclipse.persistence.sdo.helper.SDOTypeHelper; |
| import org.eclipse.persistence.sdo.helper.SDOUnmarshalListener; |
| import org.eclipse.persistence.sdo.helper.SDOXMLHelper; |
| import org.eclipse.persistence.sdo.types.SDOPropertyType; |
| import org.eclipse.persistence.sdo.types.SDOTypeType; |
| import org.eclipse.persistence.exceptions.SDOException; |
| import org.eclipse.persistence.exceptions.XMLMarshalException; |
| import org.eclipse.persistence.internal.oxm.XMLConversionManager; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.oxm.NamespaceResolver; |
| import org.eclipse.persistence.oxm.XMLContext; |
| import org.eclipse.persistence.oxm.XMLDescriptor; |
| import org.eclipse.persistence.oxm.XMLLogin; |
| import org.eclipse.persistence.oxm.XMLMarshaller; |
| import org.eclipse.persistence.oxm.XMLRoot; |
| import org.eclipse.persistence.oxm.XMLUnmarshaller; |
| import org.eclipse.persistence.oxm.attachment.XMLAttachmentMarshaller; |
| import org.eclipse.persistence.oxm.attachment.XMLAttachmentUnmarshaller; |
| import org.eclipse.persistence.oxm.record.ContentHandlerRecord; |
| import org.eclipse.persistence.oxm.record.FormattedWriterRecord; |
| import org.eclipse.persistence.oxm.record.NodeRecord; |
| import org.eclipse.persistence.oxm.record.WriterRecord; |
| import org.eclipse.persistence.sessions.Project; |
| import org.xml.sax.InputSource; |
| |
| /** |
| * <p><b>Purpose</b>: Helper to XML documents into DataObects and DataObjects into XML documents. |
| * <p><b>Responsibilities</b>:<ul> |
| * <li> Load methods create commonj.sdo.XMLDocument objects from XML (unmarshal) |
| * <li> Save methods create XML from commonj.sdo.XMLDocument and commonj.sdo.DataObject objects (marshal) |
| * </ul> |
| */ |
| public class SDOXMLHelperDelegate implements SDOXMLHelper { |
| private SDOClassLoader loader; |
| private XMLContext xmlContext; |
| |
| private Map<Thread, XMLMarshaller> xmlMarshallerMap; |
| private Map<Thread, XMLUnmarshaller> xmlUnmarshallerMap; |
| |
| private Project topLinkProject; |
| |
| // hold the context containing all helpers so that we can preserve inter-helper relationships |
| private HelperContext aHelperContext; |
| |
| public SDOXMLHelperDelegate(HelperContext aContext) { |
| this(aContext, Thread.currentThread().getContextClassLoader()); |
| } |
| |
| public SDOXMLHelperDelegate(HelperContext aContext, ClassLoader aClassLoader) { |
| aHelperContext = aContext; |
| // This ClassLoader is internal to SDO so no inter servlet-ejb container context issues should arise |
| loader = new SDOClassLoader(aClassLoader, aContext); |
| // WeakHashMap needs to be synchronized to prevent endless loop under the heavy load |
| xmlMarshallerMap = Collections.synchronizedMap(new WeakHashMap<Thread, XMLMarshaller>()); |
| xmlUnmarshallerMap = Collections.synchronizedMap(new WeakHashMap<Thread, XMLUnmarshaller>()); |
| } |
| |
| /** |
| * The specified TimeZone will be used for all String to date object |
| * conversions. By default the TimeZone from the JVM is used. |
| */ |
| @Override |
| public void setTimeZone(TimeZone timeZone) { |
| getXmlConversionManager().setTimeZone(timeZone); |
| } |
| |
| /** |
| * By setting this flag to true the marshalled date objects marshalled to |
| * the XML schema types time and dateTime will be qualified by a time zone. |
| * By default time information is not time zone qualified. |
| */ |
| @Override |
| public void setTimeZoneQualified(boolean timeZoneQualified) { |
| getXmlConversionManager().setTimeZoneQualified(timeZoneQualified); |
| } |
| |
| /** |
| * Creates and returns an XMLDocument from the input String. |
| * By default does not perform XSD validation. |
| * Same as |
| * load(new StringReader(inputString), null, null); |
| * |
| * @param inputString specifies the String to read from |
| * @return the new XMLDocument loaded |
| * @throws RuntimeException for errors in XML parsing or |
| * implementation-specific validation. |
| */ |
| @Override |
| public XMLDocument load(String inputString) { |
| StringReader reader = new StringReader(inputString); |
| try { |
| return load(reader, null, null); |
| } catch (IOException ioException) { |
| ioException.printStackTrace(); |
| return null; |
| } |
| } |
| |
| /** |
| * Creates and returns an XMLDocument from the inputStream. |
| * The InputStream will be closed after reading. |
| * By default does not perform XSD validation. |
| * Same as |
| * load(inputStream, null, null); |
| * |
| * @param inputStream specifies the InputStream to read from |
| * @return the new XMLDocument loaded |
| * @throws IOException for stream exceptions. |
| * @throws RuntimeException for errors in XML parsing or |
| * implementation-specific validation. |
| */ |
| @Override |
| public XMLDocument load(InputStream inputStream) throws IOException { |
| return load(inputStream, null, null); |
| } |
| |
| /** |
| * Creates and returns an XMLDocument from the inputStream. |
| * The InputStream will be closed after reading. |
| * By default does not perform XSD validation. |
| * @param inputStream specifies the InputStream to read from |
| * @param locationURI specifies the URI of the document for relative schema locations |
| * @param options implementation-specific options. |
| * @return the new XMLDocument loaded |
| * @throws IOException for stream exceptions. |
| * @throws RuntimeException for errors in XML parsing or |
| * implementation-specific validation. |
| */ |
| @Override |
| public XMLDocument load(InputStream inputStream, String locationURI, Object options) throws IOException { |
| InputSource inputSource = new InputSource(inputStream); |
| return load(inputSource, locationURI, options); |
| } |
| |
| /** |
| * Creates and returns an XMLDocument from the inputSource. |
| * The InputSource will be closed after reading. |
| * By default does not perform XSD validation. |
| * @param inputSource specifies the InputSource to read from |
| * @param locationURI specifies the URI of the document for relative schema locations |
| * @param options implementation-specific options. |
| * @return the new XMLDocument loaded |
| * @throws IOException for stream exceptions. |
| * @throws RuntimeException for errors in XML parsing or |
| * implementation-specific validation. |
| */ |
| @Override |
| public XMLDocument load(InputSource inputSource, String locationURI, Object options) throws IOException { |
| // get XMLUnmarshaller once - as we may create a new instance if this helper isDirty=true |
| XMLUnmarshaller anXMLUnmarshaller = getXmlUnmarshaller(options); |
| Object unmarshalledObject = null; |
| if (options == null) { |
| try { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(inputSource); |
| } catch(XMLMarshalException xmlException){ |
| handleXMLMarshalException(xmlException); |
| } |
| } else { |
| try { |
| DataObject optionsDataObject = (DataObject)options; |
| try { |
| SDOType theType = (SDOType)optionsDataObject.get(SDOConstants.TYPE_LOAD_OPTION); |
| try{ |
| if (theType != null) { |
| if(theType.isDataType()) { |
| theType = (SDOType)((SDOTypeHelper)this.aHelperContext.getTypeHelper()).getWrappersHashMap().get(theType.getQName()); |
| } |
| if(theType != null) { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(inputSource, theType.getImplClass()); |
| } else { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(inputSource); |
| } |
| }else{ |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(inputSource); |
| } |
| } catch(XMLMarshalException xmlException){ |
| handleXMLMarshalException(xmlException); |
| } |
| } catch (ClassCastException ccException) { |
| throw SDOException.typePropertyMustBeAType(ccException); |
| } |
| } catch (ClassCastException ccException) { |
| throw SDOException.optionsMustBeADataObject(ccException, SDOConstants.ORACLE_SDO_URL ,SDOConstants.XMLHELPER_LOAD_OPTIONS); |
| } |
| } |
| |
| if (unmarshalledObject instanceof XMLRoot) { |
| XMLRoot xmlRoot = (XMLRoot)unmarshalledObject; |
| XMLDocument xmlDocument = createDocument((DataObject)((XMLRoot)unmarshalledObject).getObject(), ((XMLRoot)unmarshalledObject).getNamespaceURI(), ((XMLRoot)unmarshalledObject).getLocalName()); |
| if(xmlRoot.getEncoding() != null) { |
| xmlDocument.setEncoding(xmlRoot.getEncoding()); |
| } |
| if(xmlRoot.getXMLVersion() != null) { |
| xmlDocument.setXMLVersion(xmlRoot.getXMLVersion()); |
| } |
| xmlDocument.setSchemaLocation(xmlRoot.getSchemaLocation()); |
| xmlDocument.setNoNamespaceSchemaLocation(xmlRoot.getNoNamespaceSchemaLocation()); |
| return xmlDocument; |
| } else if (unmarshalledObject instanceof DataObject) { |
| String localName = ((SDOType)((DataObject)unmarshalledObject).getType()).getXmlDescriptor().getDefaultRootElement(); |
| if (localName == null) { |
| localName = ((SDOType)((DataObject)unmarshalledObject).getType()).getXsdLocalName(); |
| } |
| return createDocument((DataObject)unmarshalledObject, ((DataObject)unmarshalledObject).getType().getURI(), localName); |
| } else if (unmarshalledObject instanceof XMLDocument) { |
| return (XMLDocument)unmarshalledObject; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Creates and returns an XMLDocument from the inputReader. |
| * The InputStream will be closed after reading. |
| * By default does not perform XSD validation. |
| * @param inputReader specifies the Reader to read from |
| * @param locationURI specifies the URI of the document for relative schema locations |
| * @param options implementation-specific options. |
| * @return the new XMLDocument loaded |
| * @throws IOException for stream exceptions. |
| * @throws RuntimeException for errors in XML parsing or |
| * implementation-specific validation. |
| */ |
| @Override |
| public XMLDocument load(Reader inputReader, String locationURI, Object options) throws IOException { |
| InputSource inputSource = new InputSource(inputReader); |
| return load(inputSource, locationURI, options); |
| } |
| |
| @Override |
| public XMLDocument load(Source source, String locationURI, Object options) throws IOException { |
| // get XMLUnmarshaller once - as we may create a new instance if this helper isDirty=true |
| XMLUnmarshaller anXMLUnmarshaller = getXmlUnmarshaller(options); |
| Object unmarshalledObject = null; |
| if (options == null) { |
| try { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(source); |
| } catch(XMLMarshalException xmlException){ |
| handleXMLMarshalException(xmlException); |
| } |
| } else { |
| try { |
| DataObject optionsDataObject = (DataObject)options; |
| try { |
| SDOType theType = (SDOType)optionsDataObject.get(SDOConstants.TYPE_LOAD_OPTION); |
| try{ |
| if (theType != null) { |
| if(theType.isDataType()) { |
| theType = (SDOType)((SDOTypeHelper)this.aHelperContext.getTypeHelper()).getWrappersHashMap().get(theType.getQName()); |
| } |
| if(theType != null) { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(source, theType.getImplClass()); |
| } else { |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(source); |
| } |
| }else{ |
| unmarshalledObject = anXMLUnmarshaller.unmarshal(source); |
| } |
| } catch(XMLMarshalException xmlException){ |
| handleXMLMarshalException(xmlException); |
| } |
| } catch (ClassCastException ccException) { |
| throw SDOException.typePropertyMustBeAType(ccException); |
| } |
| } catch (ClassCastException ccException) { |
| throw SDOException.optionsMustBeADataObject(ccException, SDOConstants.ORACLE_SDO_URL ,SDOConstants.XMLHELPER_LOAD_OPTIONS); |
| } |
| |
| } |
| |
| if (unmarshalledObject instanceof XMLRoot) { |
| XMLRoot xmlRoot = (XMLRoot)unmarshalledObject; |
| XMLDocument xmlDocument = createDocument((DataObject)((XMLRoot)unmarshalledObject).getObject(), ((XMLRoot)unmarshalledObject).getNamespaceURI(), ((XMLRoot)unmarshalledObject).getLocalName()); |
| if(xmlRoot.getEncoding() != null) { |
| xmlDocument.setEncoding(xmlRoot.getEncoding()); |
| } |
| if(xmlRoot.getXMLVersion() != null) { |
| xmlDocument.setXMLVersion(xmlRoot.getXMLVersion()); |
| } |
| xmlDocument.setSchemaLocation(xmlRoot.getSchemaLocation()); |
| xmlDocument.setNoNamespaceSchemaLocation(xmlRoot.getNoNamespaceSchemaLocation()); |
| return xmlDocument; |
| } else if (unmarshalledObject instanceof DataObject) { |
| DataObject unmarshalledDataObject = (DataObject)unmarshalledObject; |
| String localName = ((SDOType)((DataObject)unmarshalledObject).getType()).getXmlDescriptor().getDefaultRootElement(); |
| if (localName == null) { |
| localName = ((SDOType)((DataObject)unmarshalledObject).getType()).getXsdLocalName(); |
| } |
| return createDocument(unmarshalledDataObject, unmarshalledDataObject.getType().getURI(), localName); |
| } else if (unmarshalledObject instanceof XMLDocument) { |
| return (XMLDocument)unmarshalledObject; |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the DataObject saved as an XML document with the specified root element. |
| * Same as |
| * StringWriter stringWriter = new StringWriter(); |
| * save(createDocument(dataObject, rootElementURI, rootElementName), |
| * stringWriter, null); |
| * stringWriter.toString(); |
| * |
| * @param dataObject specifies DataObject to be saved |
| * @param rootElementURI the Target Namespace URI of the root XML element |
| * @param rootElementName the Name of the root XML element |
| * @return the saved XML document as a string |
| * @throws IllegalArgumentException if the dataObject tree |
| * is not closed or has no container. |
| */ |
| @Override |
| public String save(DataObject dataObject, String rootElementURI, String rootElementName) { |
| try { |
| StringWriter writer = new StringWriter(); |
| save(dataObject, rootElementURI, rootElementName, writer, getXmlMarshaller(null)); |
| return writer.toString(); |
| } catch (XMLMarshalException e) { |
| throw SDOException.xmlMarshalExceptionOccurred(e, rootElementURI, rootElementName); |
| } |
| } |
| |
| /** |
| * Saves the DataObject as an XML document with the specified root element. |
| * Same as |
| * save(createDocument(dataObject, rootElementURI, rootElementName), |
| * outputStream, null); |
| * |
| * @param dataObject specifies DataObject to be saved |
| * @param rootElementURI the Target Namespace URI of the root XML element |
| * @param rootElementName the Name of the root XML element |
| * @param outputStream specifies the OutputStream to write to. |
| * @throws IOException for stream exceptions. |
| * @throws IllegalArgumentException if the dataObject tree |
| * is not closed or has no container. |
| */ |
| @Override |
| public void save(DataObject dataObject, String rootElementURI, String rootElementName, OutputStream outputStream) throws XMLMarshalException, IOException { |
| XMLMarshaller xmlMarshaller = getXmlMarshaller(null); |
| OutputStreamWriter writer = new OutputStreamWriter(outputStream, xmlMarshaller.getEncoding()); |
| save(dataObject, rootElementURI, rootElementName, writer, xmlMarshaller); |
| } |
| |
| @Override |
| public void serialize(XMLDocument xmlDocument, OutputStream outputStream, Object options) throws IOException { |
| XMLMarshaller xmlMarshaller = getXmlMarshaller(); |
| XMLAttachmentMarshaller attachmentMarshaller = xmlMarshaller.getAttachmentMarshaller(); |
| //temporarily null out the attachment marshaller as it should not be used during serialization |
| xmlMarshaller.setAttachmentMarshaller(null); |
| OutputStreamWriter writer = new OutputStreamWriter(outputStream, xmlMarshaller.getEncoding()); |
| save(xmlDocument, writer, xmlMarshaller); |
| xmlMarshaller.setAttachmentMarshaller(attachmentMarshaller); |
| } |
| |
| /** |
| * Serializes an XMLDocument as an XML document into the outputStream. |
| * If the DataObject's Type was defined by an XSD, the serialization |
| * will follow the XSD. |
| * Otherwise the serialization will follow the format as if an XSD |
| * were generated as defined by the SDO specification. |
| * The OutputStream will be flushed after writing. |
| * Does not perform validation to ensure compliance with an XSD. |
| * @param xmlDocument specifies XMLDocument to be saved |
| * @param outputStream specifies the OutputStream to write to. |
| * @param options implementation-specific options. |
| * @throws IOException for stream exceptions. |
| * @throws IllegalArgumentException if the dataObject tree |
| * is not closed or has no container. |
| */ |
| @Override |
| public void save(XMLDocument xmlDocument, OutputStream outputStream, Object options) throws IOException { |
| if (xmlDocument == null) { |
| throw new IllegalArgumentException(SDOException.cannotPerformOperationWithNullInputParameter("save", "xmlDocument")); |
| } |
| XMLMarshaller xmlMarshaller = getXmlMarshaller(options); |
| String encoding = xmlMarshaller.getEncoding(); |
| if(xmlDocument.getEncoding() != null) { |
| encoding = xmlDocument.getEncoding(); |
| } |
| OutputStreamWriter writer = new OutputStreamWriter(outputStream, encoding); |
| save(xmlDocument, writer, xmlMarshaller); |
| } |
| |
| /** |
| * Serializes an XMLDocument as an XML document into the outputWriter. |
| * If the DataObject's Type was defined by an XSD, the serialization |
| * will follow the XSD. |
| * Otherwise the serialization will follow the format as if an XSD |
| * were generated as defined by the SDO specification. |
| * The OutputStream will be flushed after writing. |
| * Does not perform validation to ensure compliance with an XSD. |
| * @param xmlDocument specifies XMLDocument to be saved |
| * @param outputWriter specifies the Writer to write to. |
| * @param options implementation-specific options. |
| * @throws IOException for stream exceptions. |
| * @throws IllegalArgumentException if the dataObject tree |
| * is not closed or has no container. |
| */ |
| @Override |
| public void save(XMLDocument xmlDocument, Writer outputWriter, Object options) throws IOException { |
| save(xmlDocument, outputWriter, getXmlMarshaller(options)); |
| } |
| |
| private void save(XMLDocument xmlDocument, Writer outputWriter, XMLMarshaller anXMLMarshaller) throws IOException { |
| if (xmlDocument == null) { |
| throw new IllegalArgumentException(SDOException.cannotPerformOperationWithNullInputParameter("save", "xmlDocument")); |
| } |
| |
| // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML |
| anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration()); |
| |
| anXMLMarshaller.setEncoding(xmlDocument.getEncoding()); |
| anXMLMarshaller.setSchemaLocation(xmlDocument.getSchemaLocation()); |
| anXMLMarshaller.setNoNamespaceSchemaLocation(xmlDocument.getNoNamespaceSchemaLocation()); |
| |
| WriterRecord writerRecord; |
| if(anXMLMarshaller.isFormattedOutput()) { |
| writerRecord = new FormattedWriterRecord(); |
| } else { |
| writerRecord = new WriterRecord(); |
| } |
| writerRecord.setWriter(outputWriter); |
| writerRecord.setMarshaller(anXMLMarshaller); |
| |
| SDOMarshalListener listener = ((SDOMarshalListener)anXMLMarshaller.getMarshalListener()); |
| |
| listener.setMarshalledObject(xmlDocument.getRootObject()); |
| listener.setMarshalledObjectRootQName(new QName(xmlDocument.getRootElementURI(), xmlDocument.getRootElementName())); |
| listener.setRootMarshalRecord(writerRecord); |
| |
| try{ |
| anXMLMarshaller.marshal(xmlDocument, writerRecord); |
| writerRecord.flush(); |
| }catch(XMLMarshalException xme){ |
| if(xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT){ |
| if(aHelperContext != ((SDOType)xmlDocument.getRootObject().getType()).getHelperContext()){ |
| throw SDOException.dataObjectNotFromHelperContext(); |
| } |
| } |
| } finally{ |
| listener.setMarshalledObject(null); |
| listener.setMarshalledObjectRootQName(null); |
| listener.setRootMarshalRecord(null); |
| } |
| outputWriter.flush(); |
| } |
| |
| @Override |
| public void save(XMLDocument xmlDocument, Result result, Object options) throws IOException { |
| if (xmlDocument == null) { |
| throw new IllegalArgumentException(SDOException.cannotPerformOperationWithNullInputParameter("save", "xmlDocument")); |
| } |
| |
| if (result instanceof StreamResult) { |
| StreamResult streamResult = (StreamResult)result; |
| Writer writer = streamResult.getWriter(); |
| if (null == writer) { |
| save(xmlDocument, streamResult.getOutputStream(), options); |
| } else { |
| save(xmlDocument, writer, options); |
| } |
| |
| } else { |
| // get XMLMarshaller once - as we may create a new instance if this helper isDirty=true |
| XMLMarshaller anXMLMarshaller = getXmlMarshaller(options); |
| |
| // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML |
| anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration()); |
| |
| anXMLMarshaller.setEncoding(xmlDocument.getEncoding()); |
| anXMLMarshaller.setSchemaLocation(xmlDocument.getSchemaLocation()); |
| anXMLMarshaller.setNoNamespaceSchemaLocation(xmlDocument.getNoNamespaceSchemaLocation()); |
| |
| SDOMarshalListener listener = ((SDOMarshalListener)anXMLMarshaller.getMarshalListener()); |
| |
| listener.setMarshalledObject(xmlDocument.getRootObject()); |
| listener.setMarshalledObjectRootQName(new QName(xmlDocument.getRootElementURI(), xmlDocument.getRootElementName())); |
| |
| if(result instanceof SAXResult) { |
| ContentHandlerRecord marshalRecord = new ContentHandlerRecord(); |
| marshalRecord.setContentHandler(((SAXResult)result).getHandler()); |
| marshalRecord.setMarshaller(anXMLMarshaller); |
| listener.setRootMarshalRecord(marshalRecord); |
| anXMLMarshaller.marshal(xmlDocument, marshalRecord); |
| marshalRecord.flush(); |
| } else if(result instanceof DOMResult) { |
| NodeRecord marshalRecord = new NodeRecord(); |
| marshalRecord.setDOM(((DOMResult)result).getNode()); |
| marshalRecord.setMarshaller(anXMLMarshaller); |
| listener.setRootMarshalRecord(marshalRecord); |
| anXMLMarshaller.marshal(xmlDocument, marshalRecord); |
| marshalRecord.flush(); |
| } else { |
| StringWriter writer = new StringWriter(); |
| this.save(xmlDocument, writer, options); |
| String xml = writer.toString(); |
| StreamSource source = new StreamSource(new java.io.StringReader(xml)); |
| anXMLMarshaller.getTransformer().transform(source, result); |
| } |
| listener.setMarshalledObject(null); |
| listener.setMarshalledObjectRootQName(null); |
| listener.setRootMarshalRecord(null); |
| } |
| |
| } |
| |
| /** |
| * Creates an XMLDocument with the specified XML rootElement for the DataObject. |
| * @param dataObject specifies DataObject to be saved |
| * @param rootElementURI the Target Namespace URI of the root XML element |
| * @param rootElementName the Name of the root XML element |
| * @return XMLDocument a new XMLDocument set with the specified parameters. |
| */ |
| @Override |
| public XMLDocument createDocument(DataObject dataObject, String rootElementURI, String rootElementName) { |
| SDOXMLDocument document = new SDOXMLDocument(); |
| document.setRootObject(dataObject); |
| document.setRootElementURI(rootElementURI); |
| if (rootElementName != null) { |
| document.setRootElementName(rootElementName); |
| } |
| |
| Property globalProp = getHelperContext().getXSDHelper().getGlobalProperty(rootElementURI, rootElementName, true); |
| if (null != globalProp) { |
| document.setSchemaType(((SDOType) globalProp.getType()).getXsdType()); |
| } |
| |
| document.setEncoding(SDOXMLDocument.DEFAULT_XML_ENCODING); |
| document.setXMLVersion(SDOXMLDocument.DEFAULT_XML_VERSION); |
| |
| return document; |
| } |
| |
| /** |
| * INTERNAL: |
| * Saves the DataObject as an XML document with the specified root element. |
| * Same as |
| * save(createDocument(dataObject, rootElementURI, rootElementName), |
| * writer, null); |
| * |
| * @param rootObject specifies DataObject to be saved |
| * @param rootElementURI the Target Namespace URI of the root XML element |
| * @param rootElementName the Name of the root XML element |
| * @param writer specifies the Writer to write to. |
| * @throws IllegalArgumentException if the dataObject tree |
| * is not closed or has no container. |
| */ |
| private void save(DataObject rootObject, String rootElementURI, String rootElementName, Writer writer, XMLMarshaller anXMLMarshaller) throws XMLMarshalException { |
| SDOXMLDocument xmlDocument = (SDOXMLDocument)createDocument(rootObject, rootElementURI, rootElementName); |
| |
| // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML |
| anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration()); |
| WriterRecord writerRecord; |
| if(anXMLMarshaller.isFormattedOutput()) { |
| writerRecord = new FormattedWriterRecord(); |
| } else { |
| writerRecord = new WriterRecord(); |
| } |
| writerRecord.setWriter(writer); |
| writerRecord.setMarshaller(anXMLMarshaller); |
| |
| SDOMarshalListener listener = ((SDOMarshalListener)anXMLMarshaller.getMarshalListener()); |
| |
| listener.setMarshalledObject(rootObject); |
| listener.setMarshalledObjectRootQName(new QName(rootElementURI, rootElementName)); |
| listener.setRootMarshalRecord(writerRecord); |
| |
| try{ |
| anXMLMarshaller.marshal(xmlDocument, writerRecord); |
| writerRecord.flush(); |
| }catch(XMLMarshalException xme){ |
| if(xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT){ |
| if(aHelperContext != ((SDOType)rootObject.getType()).getHelperContext()){ |
| throw SDOException.dataObjectNotFromHelperContext(); |
| } |
| } |
| }finally{ |
| listener.setMarshalledObject(null); |
| listener.setMarshalledObjectRootQName(null); |
| listener.setRootMarshalRecord(null); |
| } |
| |
| |
| try { |
| writer.flush(); |
| } catch(IOException ex) { |
| throw XMLMarshalException.marshalException(ex); |
| } |
| } |
| |
| @Override |
| public void setLoader(SDOClassLoader loader) { |
| this.loader = loader; |
| getXmlConversionManager().setLoader(this.loader); |
| } |
| |
| @Override |
| public SDOClassLoader getLoader() { |
| return loader; |
| } |
| |
| @Override |
| public void setXmlContext(XMLContext xmlContext) { |
| this.xmlContext = xmlContext; |
| } |
| |
| @Override |
| public synchronized XMLContext getXmlContext() { |
| if (xmlContext == null) { |
| xmlContext = new XMLContext(getTopLinkProject()); |
| XMLConversionManager xmlConversionManager = getXmlConversionManager(); |
| xmlConversionManager.setLoader(this.loader); |
| xmlConversionManager.setTimeZone(TimeZone.getTimeZone("GMT")); |
| xmlConversionManager.setTimeZoneQualified(true); |
| } |
| return xmlContext; |
| } |
| |
| @Override |
| public void initializeDescriptor(XMLDescriptor descriptor){ |
| AbstractSession theSession = (AbstractSession)getXmlContext().getSession(); |
| |
| //do initialization for new descriptor; |
| descriptor.preInitialize(theSession); |
| descriptor.initialize(theSession); |
| descriptor.postInitialize(theSession); |
| |
| descriptor.getObjectBuilder().initializePrimaryKey(theSession); |
| getXmlContext().storeXMLDescriptorByQName(descriptor); |
| } |
| |
| @Override |
| public void addDescriptors(List types) { |
| for (int i = 0; i < types.size(); i++) { |
| SDOType nextType = (SDOType)types.get(i); |
| |
| if (!nextType.isDataType() && nextType.isFinalized()){ |
| XMLDescriptor nextDescriptor = nextType.getXmlDescriptor(); |
| getTopLinkProject().addDescriptor(nextDescriptor); |
| } |
| } |
| for (int i = 0; i < types.size(); i++) { |
| SDOType nextType = (SDOType)types.get(i); |
| if (!nextType.isDataType() && nextType.isFinalized()){ |
| XMLDescriptor nextDescriptor = nextType.getXmlDescriptor(); |
| initializeDescriptor(nextDescriptor); |
| } |
| } |
| } |
| |
| @Override |
| public void setTopLinkProject(Project toplinkProject) { |
| this.topLinkProject = toplinkProject; |
| this.xmlContext = null; |
| this.xmlMarshallerMap.clear(); |
| this.xmlUnmarshallerMap.clear(); |
| } |
| |
| @Override |
| public Project getTopLinkProject() { |
| if (topLinkProject == null) { |
| topLinkProject = new Project(); |
| XMLLogin xmlLogin = new XMLLogin(); |
| xmlLogin.setEqualNamespaceResolvers(false); |
| topLinkProject.setDatasourceLogin(xmlLogin); |
| // 200606_changeSummary |
| NamespaceResolver nr = new NamespaceResolver(); |
| SDOTypeHelper sdoTypeHelper = (SDOTypeHelper) aHelperContext.getTypeHelper(); |
| String sdoPrefix = sdoTypeHelper.getPrefix(SDOConstants.SDO_URL); |
| nr.put(sdoPrefix, SDOConstants.SDO_URL); |
| SDOType changeSummaryType = (SDOType) sdoTypeHelper.getType(SDOConstants.SDO_URL, SDOConstants.CHANGESUMMARY); |
| changeSummaryType.getXmlDescriptor().setNamespaceResolver(nr); |
| topLinkProject.addDescriptor(changeSummaryType.getXmlDescriptor()); |
| SDOType openSequencedType = (SDOType) aHelperContext.getTypeHelper().getType(SDOConstants.ORACLE_SDO_URL, "OpenSequencedType"); |
| topLinkProject.addDescriptor(openSequencedType.getXmlDescriptor()); |
| SDOTypeType typeType = (SDOTypeType)aHelperContext.getTypeHelper().getType(SDOConstants.SDO_URL, SDOConstants.TYPE); |
| typeType.getXmlDescriptor().setNamespaceResolver(nr); |
| if(!typeType.isInitialized()) { |
| typeType.initializeMappings(); |
| } |
| topLinkProject.addDescriptor(typeType.getXmlDescriptor()); |
| SDOPropertyType propertyType = (SDOPropertyType)aHelperContext.getTypeHelper().getType(SDOConstants.SDO_URL, SDOConstants.PROPERTY); |
| if(!propertyType.isInitialized()) { |
| propertyType.initializeMappings(); |
| } |
| topLinkProject.addDescriptor(propertyType.getXmlDescriptor()); |
| |
| ((SDOTypeHelper)aHelperContext.getTypeHelper()).addWrappersToProject(topLinkProject); |
| } |
| return topLinkProject; |
| } |
| |
| @Override |
| public void setXmlMarshaller(XMLMarshaller xmlMarshaller) { |
| this.xmlMarshallerMap.put(Thread.currentThread(), xmlMarshaller); |
| } |
| |
| @Override |
| public XMLMarshaller getXmlMarshaller() { |
| XMLMarshaller marshaller = xmlMarshallerMap.get(Thread.currentThread()); |
| |
| if (marshaller == null) { |
| marshaller = getXmlContext().createMarshaller(); |
| marshaller.setMarshalListener(new SDOMarshalListener(marshaller, (SDOTypeHelper) aHelperContext.getTypeHelper())); |
| xmlMarshallerMap.put(Thread.currentThread(), marshaller); |
| } |
| |
| XMLContext context = getXmlContext(); |
| if (marshaller.getXMLContext() != context) { |
| marshaller.setXMLContext(context); |
| } |
| return marshaller; |
| } |
| |
| private XMLMarshaller getXmlMarshaller(Object options) { |
| XMLMarshaller xmlMarshaller = getXmlMarshaller().clone(); |
| if(null == options) { |
| return xmlMarshaller; |
| } |
| try { |
| DataObject optionsDO = (DataObject) options; |
| if(optionsDO.isSet(SDOConstants.ATTACHMENT_MARSHALLER_OPTION)) { |
| xmlMarshaller.setAttachmentMarshaller((XMLAttachmentMarshaller)optionsDO.get(SDOConstants.ATTACHMENT_MARSHALLER_OPTION)); |
| } |
| xmlMarshaller.setMarshalListener(new SDOMarshalListener(xmlMarshaller, (SDOTypeHelper) aHelperContext.getTypeHelper())); |
| return xmlMarshaller; |
| } catch(ClassCastException ccException) { |
| throw SDOException.optionsMustBeADataObject(ccException, SDOConstants.ORACLE_SDO_URL ,SDOConstants.XMLHELPER_LOAD_OPTIONS); |
| } |
| } |
| |
| @Override |
| public void setXmlUnmarshaller(XMLUnmarshaller xmlUnmarshaller) { |
| this.xmlUnmarshallerMap.put(Thread.currentThread(), xmlUnmarshaller); |
| } |
| |
| @Override |
| public XMLUnmarshaller getXmlUnmarshaller() { |
| XMLUnmarshaller unmarshaller = xmlUnmarshallerMap.get(Thread.currentThread()); |
| |
| if (null == unmarshaller) { |
| unmarshaller = getXmlContext().createUnmarshaller(); |
| unmarshaller.getProperties().put(SDOConstants.SDO_HELPER_CONTEXT, aHelperContext); |
| unmarshaller.setUnmappedContentHandlerClass(SDOUnmappedContentHandler.class); |
| unmarshaller.setUnmarshalListener(new SDOUnmarshalListener(aHelperContext)); |
| unmarshaller.setResultAlwaysXMLRoot(true); |
| xmlUnmarshallerMap.put(Thread.currentThread(), unmarshaller); |
| } |
| |
| XMLContext context = getXmlContext(); |
| if (unmarshaller.getXMLContext() != context) { |
| unmarshaller.setXMLContext(context); |
| } |
| return unmarshaller; |
| } |
| |
| private XMLUnmarshaller getXmlUnmarshaller(Object options) { |
| XMLUnmarshaller xmlUnmarshaller = getXmlUnmarshaller().clone(); |
| if(null == options) { |
| return xmlUnmarshaller; |
| } |
| try { |
| DataObject optionsDO = (DataObject) options; |
| if(optionsDO.isSet(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION)) { |
| xmlUnmarshaller.setAttachmentUnmarshaller((XMLAttachmentUnmarshaller)optionsDO.get(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION)); |
| } |
| return xmlUnmarshaller; |
| } catch(ClassCastException ccException) { |
| throw SDOException.optionsMustBeADataObject(ccException, SDOConstants.ORACLE_SDO_URL ,SDOConstants.XMLHELPER_LOAD_OPTIONS); |
| } |
| } |
| |
| @Override |
| public void reset() { |
| setTopLinkProject(null); |
| setXmlContext(null); |
| this.xmlMarshallerMap.clear(); |
| this.xmlUnmarshallerMap.clear(); |
| setLoader(new SDOClassLoader(getClass().getClassLoader(), aHelperContext)); |
| } |
| |
| @Override |
| public HelperContext getHelperContext() { |
| return aHelperContext; |
| } |
| |
| @Override |
| public void setHelperContext(HelperContext helperContext) { |
| aHelperContext = helperContext; |
| } |
| |
| private void handleXMLMarshalException(XMLMarshalException xmlException) throws IOException { |
| if(xmlException.getErrorCode() == XMLMarshalException.NO_DESCRIPTOR_WITH_MATCHING_ROOT_ELEMENT || xmlException.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT){ |
| throw SDOException.globalPropertyNotFound(); |
| } else if (xmlException.getCause() instanceof IOException) { |
| throw (IOException) xmlException.getCause(); |
| } else{ |
| throw xmlException; |
| } |
| } |
| |
| @Override |
| public XMLConversionManager getXmlConversionManager() { |
| return (XMLConversionManager) getXmlContext().getSession().getDatasourceLogin().getDatasourcePlatform().getConversionManager(); |
| } |
| |
| } |