/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * http://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.xml.ws.db.sdo; import commonj.sdo.DataObject; import commonj.sdo.Type; import commonj.sdo.helper.DataFactory; import commonj.sdo.helper.HelperContext; import commonj.sdo.helper.XMLDocument; import org.eclipse.persistence.sdo.SDOConstants; import org.eclipse.persistence.sdo.helper.SDODataHelper; import org.eclipse.persistence.sdo.helper.SDOXMLHelper; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; import com.sun.xml.ws.util.xml.XmlUtil; import com.sun.xml.ws.spi.db.BindingContext; import com.sun.xml.ws.spi.db.TypeInfo; import com.sun.xml.ws.spi.db.XMLBridge; import javax.xml.bind.JAXBException; import javax.xml.bind.attachment.AttachmentMarshaller; import javax.xml.bind.attachment.AttachmentUnmarshaller; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.*; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.InputStream; import java.io.OutputStream; import java.util.logging.Level; import java.util.logging.Logger; public class SDOBond<T> implements XMLBridge<T> { private static final String CLASSNAME = SDOBond.class.getName(); private static final Logger logger = Logger.getLogger(CLASSNAME); private TypeInfo ti; private QName xmlTag = null; private Class<T> javaType = null; private Type theType = null; private SDOContextWrapper parent; TransformerFactory tf = XmlUtil.newTransformerFactory(false); DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(false); public SDOBond(SDOContextWrapper parent, TypeInfo ti) { this.parent = parent; this.ti = ti; this.javaType = (Class<T>) ti.type; this.xmlTag = ti.tagName; HelperContext context = parent.getHelperContext(); this.theType = context.getTypeHelper().getType(javaType); } // public SDOBond(Class<T> type, QName xml) { // logger.entering("SDOBond", "constructor"); // javaType = type; // xmlTag = xml; // HelperContext context = parent.getHelperContext(); // this.theType = context.getTypeHelper().getType(javaType); // } public QName getXmlTag() { return xmlTag; } public Class<T> getJavaType() { return javaType; } private T deserialize(Source src, javax.xml.bind.attachment.AttachmentUnmarshaller au) { try { if (!commonj.sdo.DataObject.class.isAssignableFrom(javaType) && !javaType.isInterface()) { return (T) deserializePrimitives(src); } HelperContext context = parent.getHelperContext(); SDOAttachmentUnmarshaller unmarshaller = null; if (au != null) { unmarshaller = new SDOAttachmentUnmarshaller(au); } DataFactory dataFactory = context.getDataFactory(); DataObject loadOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS); //bug 8680450 loadOptions.set(SDOConstants.TYPE_LOAD_OPTION, theType); if (unmarshaller != null) { loadOptions.set(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION, unmarshaller); } XMLDocument xdoc = context.getXMLHelper().load(src, null, loadOptions); DataObject obj = xdoc.getRootObject(); Object o = SDOUtils.unwrapPrimitives(obj); return (T) o; // ClassCast possible without check } catch (Exception e) { throw new SDODatabindingException(e); } } private Object deserializePrimitives(Source src) throws Exception { if (javaType == null) { return null; } String value = null; if (src instanceof StAXSource) { StAXSource staxSrc = (StAXSource)src; XMLStreamReader xr = staxSrc.getXMLStreamReader(); if(xr.isStartElement()) { xr.next(); } StringBuilder sb = new StringBuilder(); while(xr.isCharacters()) { sb.append(xr.getText()); xr.next(); } value = sb.toString().trim(); } else { DOMResult result = new DOMResult(); Transformer t = tf.newTransformer(); t.transform(src, result); value = ((Document)result.getNode()).getDocumentElement().getTextContent().trim(); //xmlElement.getTextContent().trim(); } if (value == null) { return null; } Object o = null; try { o = ((SDODataHelper) parent.getHelperContext().getDataHelper()).convertFromStringValue(value, theType); } catch (Exception e) { // content class does not accept null or empty value, such as BigDecimal, Integer etc // these type of empty value will cause toplink data helper to fail, workaround to prevent such failures if (value.length() == 0) { if (logger.isLoggable(Level.FINEST)) { logger.finest("Deserialized primitive part has 0 length text, result is null"); } return null; } } if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "Deserialized primitive part {0}", o); } return o; } private String serializePrimitive(Object obj, Class<?> contentClass) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "Primitive class to be serialized ==> {0}", contentClass); } HelperContext context = parent.getHelperContext(); Type type = context.getTypeHelper().getType(contentClass); if (type != null) { return ((SDODataHelper) context.getDataHelper()).convertToStringValue(obj, type); } if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Invalid SDO primitive type: {0}", contentClass.getClass().getName()); } throw new SDODatabindingException("Invalid SDO primitive type: " + contentClass.getClass().getName()); } private void serializeToResult(String value, Result result) { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); Element elt = doc.createElementNS(xmlTag.getNamespaceURI(), "ns1:" + xmlTag.getLocalPart()); doc.appendChild(elt); elt.appendChild(doc.createTextNode(value)); DOMSource ds = new DOMSource(elt); Transformer t = tf.newTransformer(); t.transform(ds, result); } catch (Exception e) { throw new SDODatabindingException(e.getMessage()); } } @Override public BindingContext context() { return parent; } private void serializeDataObject(DataObject java, Result result, javax.xml.bind.attachment.AttachmentMarshaller am) { logger.entering(CLASSNAME, "serializeDataObject"); try { HelperContext context = parent.getHelperContext(); SDOAttachmentMarshaller marshaller = null; if (am != null) { marshaller = new SDOAttachmentMarshaller(am); } // check Primitives for T SDOXMLHelper sdoXMLHelper = (SDOXMLHelper) context.getXMLHelper(); // Bug 8909750 - Toplink already sets this to "GMT". ADF // resets it before we get here, so don't change it again. //sdoXMLHelper.setTimeZone(TimeZone.getTimeZone("GMT")); sdoXMLHelper.setTimeZoneQualified(true); XMLDocument xmlDoc = sdoXMLHelper.createDocument((DataObject) java, xmlTag.getNamespaceURI(), xmlTag.getLocalPart()); if (xmlDoc == null) { return; } xmlDoc.setXMLDeclaration(false); DataObject saveOptions = null; if (marshaller != null) { DataFactory dataFactory = parent.getHelperContext().getDataFactory(); saveOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS); saveOptions.set(SDOConstants.ATTACHMENT_MARSHALLER_OPTION, marshaller); } sdoXMLHelper.save(xmlDoc, result, saveOptions); } catch (Exception e) { throw new SDODatabindingException(e); } } @Override public void marshal(T object, XMLStreamWriter output, AttachmentMarshaller am) throws JAXBException { /* Didn't work due to bug 8539542 StAXResult result = new StAXResult(writer); sdoXMLHelper.save(xmlDoc, result, null); */ try { output.flush(); } catch (Exception e) { e.printStackTrace(); } SAX2StaxContentHandler handler = new SAX2StaxContentHandler(output); if (object instanceof DataObject) { serializeDataObject((DataObject) object, new SAXResult(handler), am); return; } try { String value = serializePrimitive(object, javaType); String prefix = output.getPrefix(xmlTag.getNamespaceURI()); //TODO, this is a hack, seems to be wrong. why should namespace returned is ""? if (xmlTag.getNamespaceURI().equals("")) { output.writeStartElement("", xmlTag.getLocalPart(), xmlTag.getNamespaceURI()); // } else if (prefix == null) { // output.writeStartElement(xmlTag.getNamespaceURI(), xmlTag.getLocalPart()); } else { output.writeStartElement(prefix, xmlTag.getLocalPart(), xmlTag.getNamespaceURI()); output.writeNamespace(prefix, xmlTag.getNamespaceURI()); } output.writeCharacters(value); output.writeEndElement(); } catch (XMLStreamException e) { throw new SDODatabindingException(e); } } @Override public void marshal(T object, OutputStream output, NamespaceContext nsContext, AttachmentMarshaller am) throws JAXBException { if (object instanceof DataObject) { serializeDataObject((DataObject) object, new StreamResult(output), am); return; } try { String value = serializePrimitive(object, javaType); String prefix = nsContext.getPrefix(xmlTag.getNamespaceURI()); StringBuilder sb = new StringBuilder(); if ("".equals(prefix)) { sb.append("<").append(xmlTag.getLocalPart()).append(">"); sb.append(value); sb.append("</").append(xmlTag.getLocalPart()).append(">"); } else if (prefix != null) { sb.append("<").append(prefix).append(":") .append(xmlTag.getLocalPart()).append(">"); sb.append(value); sb.append("</").append(prefix).append(":") .append(xmlTag.getLocalPart()).append(">"); } else { // Unbound namespace! sb.append("<ns1:").append(xmlTag.getLocalPart()) .append(" xmlns:ns1=\"") .append(xmlTag.getNamespaceURI()).append("\"") .append(">"); sb.append(value); sb.append("</ns1:").append(xmlTag.getLocalPart()).append(">"); } } catch (Exception e) { throw new SDODatabindingException(e); } } @Override public void marshal(T object, Node output) throws JAXBException { Result res = new DOMResult(output); if (object instanceof DataObject) { serializeDataObject((DataObject) object, res, null); return; } String value = serializePrimitive(object, javaType); serializeToResult(value, res); } @Override public void marshal(T object, ContentHandler contentHandler, AttachmentMarshaller am) throws JAXBException { Result res = new SAXResult(contentHandler); if (object instanceof DataObject) { serializeDataObject((DataObject) object, res, null); return; } String value = serializePrimitive(object, javaType); serializeToResult(value, res); } @Override public void marshal(T object, Result result) throws JAXBException { if (object instanceof DataObject) { serializeDataObject((DataObject) object, result, null); return; } String value = serializePrimitive(object, javaType); serializeToResult(value, result); } @Override public T unmarshal(XMLStreamReader in, AttachmentUnmarshaller au) throws JAXBException { return deserialize(new StAXSource(in), au); } @Override public T unmarshal(Source in, AttachmentUnmarshaller au) throws JAXBException { return deserialize(in, au); } @Override public T unmarshal(InputStream in) throws JAXBException { return deserialize(new StreamSource(in), null); } @Override public T unmarshal(Node n, AttachmentUnmarshaller au) throws JAXBException { return deserialize(new DOMSource(n), au); } @Override public TypeInfo getTypeInfo() { return ti; } @Override public boolean supportOutputStream() { return true; } }