/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.binding.celtix.io; import java.util.List; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.apache.tuscany.spi.wire.InvocationRuntimeException; import commonj.sdo.DataObject; import commonj.sdo.Property; import commonj.sdo.Type; import commonj.sdo.helper.DataFactory; import commonj.sdo.helper.TypeHelper; import commonj.sdo.helper.XMLDocument; import commonj.sdo.helper.XMLHelper; import commonj.sdo.helper.XSDHelper; import org.apache.tuscany.databinding.sdo.XMLDocument2XMLStreamReader; import org.apache.tuscany.sdo.util.SDOUtil; import org.objectweb.celtix.bindings.DataWriter; import org.objectweb.celtix.context.ObjectMessageContext; public class NodeDataWriter implements DataWriter { private static final String XML_NS = "http://www.w3.org/2000/xmlns/"; private SCADataBindingCallback callback; public NodeDataWriter(SCADataBindingCallback cb) { callback = cb; } public void write(Object obj, Node output) { write(obj, null, output); } public void write(Object obj, QName elName, Node output) { boolean isWrapped = false; XMLDocument document = toXMLDocument(callback.getTypeHelper(), new Object[]{obj}, elName, isWrapped); // HACK: [rfeng] We should use the transformer in an interceptor XMLDocument2XMLStreamReader transformer = new XMLDocument2XMLStreamReader(); XMLStreamReader reader = transformer.transform(document, null); try { //CeltixFire supports Stax, we should not need to do following anymore. readDocElements(output, reader, true, null); } catch (XMLStreamException e) { throw new InvocationRuntimeException(e.getMessage()); } } public void writeWrapper(ObjectMessageContext objCtx, boolean isOutbound, Node output) { boolean isWrapped = true; QName wrapperName; if (isOutbound) { wrapperName = callback.getOperationInfo().getResponseWrapperQName(); } else { wrapperName = callback.getOperationInfo().getRequestWrapperQName(); } XMLDocument document = toXMLDocument( callback.getTypeHelper(), objCtx.getMessageObjects(), wrapperName, isWrapped); // HACK: [rfeng] We should use the transformer in an interceptor XMLDocument2XMLStreamReader transformer = new XMLDocument2XMLStreamReader(); XMLStreamReader reader = transformer.transform(document, null); try { readDocElements(output, reader, true, null); } catch (XMLStreamException e) { e.printStackTrace(); throw new InvocationRuntimeException(e.getMessage()); } } /* private DataObject toWrappedDataObject(TypeHelper typeHelper, Object ret, Object[] os, QName typeQN) { XSDHelper xsdHelper = new XSDHelperImpl(typeHelper); Property property = xsdHelper.getGlobalProperty(typeQN.getNamespaceURI(), typeQN.getLocalPart(), true); DataObject dataObject = new DataFactoryImpl(typeHelper).create(property.getType()); List ips = dataObject.getInstanceProperties(); int offset = 0; if (ret != null) { dataObject.set(0, ret); offset = 1; } for (int i = offset; i < ips.size(); i++) { if (os[i - offset] instanceof Holder) { Holder holder = (Holder)os[i - offset]; dataObject.set(i, holder.value); } else { dataObject.set(i, os[i - offset]); } } return dataObject; } */ /** * Convert objects to typed DataObject * * @param typeHelper * @param os * @param elementQName * @param isWrapped * @return the DataObject */ private static XMLDocument toXMLDocument(TypeHelper typeHelper, Object[] os, QName elementQName, boolean isWrapped) { XSDHelper xsdHelper = SDOUtil.createXSDHelper(typeHelper); Property property = xsdHelper.getGlobalProperty( elementQName.getNamespaceURI(), elementQName.getLocalPart(), true); if (null == property) { throw new InvocationRuntimeException( "Type '" + elementQName.toString() + "' not found in registered SDO types."); } DataObject dataObject; if (isWrapped) { DataFactory dataFactory = SDOUtil.createDataFactory(typeHelper); dataObject = dataFactory.create(property.getType()); List ips = dataObject.getInstanceProperties(); for (int i = 0; i < ips.size(); i++) { dataObject.set(i, os[i]); } } else { Object value = os[0]; Type type = property.getType(); if (!type.isDataType()) { dataObject = (DataObject) value; } else { dataObject = SDOUtil.createDataTypeWrapper(type, value); } } XMLHelper xmlHelper = SDOUtil.createXMLHelper(typeHelper); return xmlHelper.createDocument(dataObject, elementQName.getNamespaceURI(), elementQName.getLocalPart()); } //REVISIT: We should not need to do following anymore with CeltixFire. //As CeltixFire supports stax directly. /** * @param parent * @param reader * @param repairing * @param stopAt: stop at the specified element * @throws XMLStreamException */ public static void readDocElements(Node parent, XMLStreamReader reader, boolean repairing, QName stopAt) throws XMLStreamException { Document doc = getDocument(parent); int event = reader.getEventType(); while (reader.hasNext()) { switch (event) { case XMLStreamConstants.START_ELEMENT: if (startElement(parent, reader, repairing, stopAt) == null) { return; } if (parent instanceof Document && stopAt != null) { if (reader.hasNext()) { reader.next(); } return; } break; case XMLStreamConstants.END_ELEMENT: return; case XMLStreamConstants.NAMESPACE: break; case XMLStreamConstants.ATTRIBUTE: break; case XMLStreamConstants.CHARACTERS: if (parent != null) { parent.appendChild(doc.createTextNode(reader.getText())); } break; case XMLStreamConstants.COMMENT: if (parent != null) { parent.appendChild(doc.createComment(reader.getText())); } break; case XMLStreamConstants.CDATA: parent.appendChild(doc.createCDATASection(reader.getText())); break; case XMLStreamConstants.PROCESSING_INSTRUCTION: parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(), reader.getPIData())); break; case XMLStreamConstants.ENTITY_REFERENCE: parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(), reader.getPIData())); break; default: break; } if (reader.hasNext()) { event = reader.next(); } } } private static Document getDocument(Node parent) { return (parent instanceof Document) ? (Document) parent : parent.getOwnerDocument(); } /** * @param parent * @param reader * @return * @throws XMLStreamException */ private static Element startElement(Node parent, XMLStreamReader reader, boolean repairing, QName stopAt) throws XMLStreamException { Document doc = getDocument(parent); if (stopAt != null && stopAt.getNamespaceURI().equals(reader.getNamespaceURI()) && stopAt.getLocalPart().equals(reader.getLocalName())) { return null; } Element e = doc.createElementNS(reader.getNamespaceURI(), reader.getLocalName()); if (reader.getPrefix() != null) { e.setPrefix(reader.getPrefix()); } parent.appendChild(e); for (int ns = 0; ns < reader.getNamespaceCount(); ns++) { String uri = reader.getNamespaceURI(ns); String prefix = reader.getNamespacePrefix(ns); declare(e, uri, prefix); } for (int att = 0; att < reader.getAttributeCount(); att++) { String name = reader.getAttributeLocalName(att); String prefix = reader.getAttributePrefix(att); if (prefix != null && prefix.length() > 0) { name = prefix + ":" + name; } Attr attr = doc.createAttributeNS(reader.getAttributeNamespace(att), name); attr.setValue(reader.getAttributeValue(att)); e.setAttributeNode(attr); } reader.next(); readDocElements(e, reader, repairing, stopAt); if (repairing && !isDeclared(e, reader.getNamespaceURI(), reader.getPrefix())) { declare(e, reader.getNamespaceURI(), reader.getPrefix()); } return e; } private static void declare(Element node, String uri, String prefix) { if (prefix != null && prefix.length() > 0) { node.setAttributeNS(XML_NS, "xmlns:" + prefix, uri); } else { if (uri != null /* && uri.length() > 0 */) { node.setAttributeNS(XML_NS, "xmlns", uri); } } } private static boolean isDeclared(Element e, String namespaceURI, String prefix) { Attr att; if (prefix != null && prefix.length() > 0) { att = e.getAttributeNodeNS(XML_NS, "xmlns:" + prefix); } else { att = e.getAttributeNode("xmlns"); } if (att != null && att.getNodeValue().equals(namespaceURI)) { return true; } if (e.getParentNode() instanceof Element) { return isDeclared((Element) e.getParentNode(), namespaceURI, prefix); } return false; } }