Package org.objectweb.celtix.bus.bindings.xml

Source Code of org.objectweb.celtix.bus.bindings.xml.XMLBindingImpl

package org.objectweb.celtix.bus.bindings.xml;

import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jws.WebParam;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.jws.soap.SOAPBinding.Style;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Port;
import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;
import javax.xml.ws.Holder;
import javax.xml.ws.WebFault;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;

import org.w3c.dom.*;

import org.objectweb.celtix.Bus;
import org.objectweb.celtix.bindings.AbstractBindingImpl;
import org.objectweb.celtix.bindings.DataBindingCallback;
import org.objectweb.celtix.bindings.DataReader;
import org.objectweb.celtix.bindings.DataWriter;
import org.objectweb.celtix.bindings.xmlformat.TBody;
import org.objectweb.celtix.bus.handlers.HandlerChainInvoker;
import org.objectweb.celtix.common.logging.LogUtils;
import org.objectweb.celtix.context.InputStreamMessageContext;
import org.objectweb.celtix.context.ObjectMessageContext;
import org.objectweb.celtix.context.OutputStreamMessageContext;
import org.objectweb.celtix.handlers.HandlerInvoker;
import org.objectweb.celtix.helpers.NodeUtils;
import org.objectweb.celtix.helpers.WSDLHelper;
import org.objectweb.celtix.helpers.XMLUtils;
import org.objectweb.celtix.ws.addressing.EndpointReferenceType;
import org.objectweb.celtix.wsdl.EndpointReferenceUtils;

public class XMLBindingImpl extends AbstractBindingImpl {
    private static final Logger LOG = LogUtils.getL7dLogger(XMLBindingImpl.class);
    protected final XMLMessageFactory msgFactory;
    protected final boolean isServer;
    private final XMLUtils xmlUtils = new XMLUtils();

    private Bus bus;
    private EndpointReferenceType endpointRef;
   
    public XMLBindingImpl(boolean server) {
        isServer = server;
        msgFactory = XMLMessageFactory.newInstance();
    }

    public XMLBindingImpl(Bus b, EndpointReferenceType ert, boolean server) {
        this(server);
        this.bus = b;
        this.endpointRef = ert;
    }

    public Bus getBus() {
        return this.bus;
    }

    public EndpointReferenceType getEndpointReference() {
        return this.endpointRef;
    }
   
    // --- AbstractBindingImpl interface ---

    public MessageContext createBindingMessageContext(MessageContext srcCtx) {
        return new XMLMessageContextImpl(srcCtx);
    }

    public HandlerInvoker createHandlerInvoker() {
        return new HandlerChainInvoker(getHandlerChain(true));
    }

    public XMLMessageFactory getMessageFactory() {
        return this.msgFactory;
    }

    private XMLMessage initXMLMessage() {
        return msgFactory.createMessage();
    }

    public void marshal(ObjectMessageContext objContext, MessageContext mc, DataBindingCallback callback) {
        try {
            LOG.entering(getClass().getName(), "marshal");
            boolean isInputMsg = (Boolean)mc.get(ObjectMessageContext.MESSAGE_INPUT);
            XMLMessage msg = initXMLMessage();
            LOG.log(Level.INFO, "XML_MARSHALLING_START", xmlUtils.toString(msg.getRoot()));
            if (callback.getMode() == DataBindingCallback.Mode.PARTS) {
                if (callback.getSOAPStyle() == Style.DOCUMENT
                    && callback.getSOAPParameterStyle() == ParameterStyle.BARE) {
                    if (isInputMsg) {
                        addReturnWrapperRoot(msg, callback);
                        LOG.log(Level.INFO, "XML_MARSHALLING_BARE_OUT", xmlUtils.toString(msg.getRoot()));
                    } else {
                        addWrapperRoot(msg, callback);
                        LOG.log(Level.INFO, "XML_MARSHALLING_BARE_IN", xmlUtils.toString(msg.getRoot()));

                    }
                }
                addParts(msg.getRoot(), objContext, isInputMsg, callback);
            } else if (callback.getMode() == DataBindingCallback.Mode.MESSAGE) {
                throw new XMLBindingException("Could not figure out how to marshal data");
            } else if (callback.getMode() == DataBindingCallback.Mode.PAYLOAD) {
                throw new XMLBindingException("Could not figure out how to marshal data");
            }
            LOG.log(Level.INFO, "XML_MARSHALLING_END", xmlUtils.toString(msg.getRoot()));
            ((XMLMessageContext)mc).setMessage(msg);
            LOG.exiting(getClass().getName(), "marshal", "XML binding Mashal OK");
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "XML_MARSHALLING_FAILURE_MSG", e);
            throw new XMLBindingException("XML binding marshal exception ", e);
        }
    }
   
    public void marshalFault(ObjectMessageContext objContext,
                             MessageContext mc,
                             DataBindingCallback callback) {
        XMLMessage msg = null;
       
        try {
            msg = XMLMessageContext.class.isInstance(mc) && ((XMLMessageContext)mc).getMessage() != null
                ? ((XMLMessageContext)mc).getMessage() : initXMLMessage();
            if (msg.hasChildNodes()) {
                msg.removeContents();
            }
           
            Throwable t = objContext.getException();
           
            XMLFault fault = msg.addFault();
            // REVIST FaultCode to handle other codes.
            StringBuffer str = new StringBuffer(t.toString());
            if (!t.getClass().isAnnotationPresent(WebFault.class)) {
                str.append("\n");
                for (StackTraceElement s : t.getStackTrace()) {
                    str.append(s.toString());
                    str.append("\n");
                }
            }
            fault.addFaultString(str.toString());

            DataWriter<XMLFault> writer = callback.createWriter(XMLFault.class);
            if (writer != null) {
                writer.write(t, fault);
                if (fault.getFaultDetail() != null && !fault.getFaultDetail().hasChildNodes()) {
                    fault.removeChild(fault.getFaultDetail());
                }
            }
        } catch (XMLBindingException se) {
            LOG.log(Level.SEVERE, "FAULT_MARSHALLING_FAILURE_MSG", se);
            // Handle UnChecked Exception, Runtime Exception.
        }
        ((XMLMessageContext)mc).setMessage(msg);
    }

    public void unmarshal(MessageContext mc, ObjectMessageContext objContext, DataBindingCallback callback) {
        try {
            LOG.entering(getClass().getName(), "unmarshal");

            boolean isOutputMsg = (Boolean)mc.get(ObjectMessageContext.MESSAGE_INPUT);
            if (!XMLMessageContext.class.isInstance(mc)) {
                throw new XMLBindingException("XMLMessageContext not available");
            }
           
            XMLMessageContext xmlContext = XMLMessageContext.class.cast(mc);
            XMLMessage xmlMessage = xmlContext.getMessage();
           
            if (callback.getMode() == DataBindingCallback.Mode.PARTS) {
                Node root = xmlMessage.getRoot();
                LOG.log(Level.INFO, "XML_UNMARSHALLING_START", xmlUtils.toString(root));
                getParts(root, callback, objContext, isOutputMsg);
                LOG.log(Level.INFO, "XML_UNMARSHALLING_END", xmlUtils.toString(root));
            } else if (callback.getMode() == DataBindingCallback.Mode.MESSAGE) {
                throw new XMLBindingException("Could not figure out how to marshal data");
            } else if (callback.getMode() == DataBindingCallback.Mode.PAYLOAD) {
                throw new XMLBindingException("Could not figure out how to marshal data");
            }
            LOG.exiting(getClass().getName(), "unmarshal", "XML binding Unmashal OK");
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "XML_UNMARSHALLING_FAILURE_MSG", e);
            throw new XMLBindingException("XML binding unmarshal exception", e);
        }
    }
   
    public void unmarshalFault(MessageContext context, ObjectMessageContext objContext,
                               DataBindingCallback callback) {
        try {
            if (!XMLMessageContext.class.isInstance(context)) {
                throw new XMLBindingException("XMLMessageContext not available");
            }
           
            XMLMessageContext xmlContext = XMLMessageContext.class.cast(context);
            XMLMessage xmlMessage = xmlContext.getMessage();
           
            XMLFault fault = xmlMessage.getFault();
            if (fault == null) {
                fault = xmlMessage.addFault();
                fault.addFaultString("Unknow fault raised, the fault is null");
            }
            DataReader<XMLFault> reader = callback.createReader(XMLFault.class);
           
            if (reader == null) {
                throw new WebServiceException("Could not unmarshal fault");
            }
            Object faultObj = reader.read(null, 0, fault);
           
            objContext.setException((Throwable)faultObj);
        } catch (Exception se) {
            LOG.log(Level.SEVERE, "XML_UNMARSHALLING_FAILURE_MSG", se);
            throw new XMLBindingException("XML binding unmarshal fault exception", se);
        }
    }

    public void write(MessageContext msgContext, OutputStreamMessageContext outContext) throws IOException {
        XMLMessageContext xmlContext = (XMLMessageContext)msgContext;
        try {
            xmlContext.getMessage().writeTo(outContext.getOutputStream());
           
            if (LOG.isLoggable(Level.FINE)) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                xmlContext.getMessage().writeTo(baos);
                LOG.log(Level.FINE, baos.toString());
            }
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "XML_WRITE_FAILURE_MSG", e);
            throw new XMLBindingException("XML binding write exception ", e);
        }
    }
   
    public void read(InputStreamMessageContext inContext, MessageContext context) throws IOException {
        if (!XMLMessageContext.class.isInstance(context)) {
            throw new XMLBindingException("XMLMessageContext not available");
        }
        try {
            XMLMessageContext xmlContext = XMLMessageContext.class.cast(context);
            xmlContext.setMessage(msgFactory.createMessage(inContext.getInputStream()));
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "XML_READ_FAILURE_MSG", e);
            throw new XMLBindingException("XML binding read exception ", e);
        }
    }

    public boolean hasFault(MessageContext msgContext) {
        XMLMessage msg = ((XMLMessageContext)msgContext).getMessage();
        assert msg != null;
        return msg.hasFault();
    }

    public void updateMessageContext(MessageContext msgContext) {
        // TODO
    }

    private void getParts(Node xmlNode, DataBindingCallback callback, ObjectMessageContext objCtx,
                          boolean isOutBound) throws XMLBindingException {
        DataReader<Node> reader = null;
        for (Class<?> cls : callback.getSupportedFormats()) {
            if (cls == Node.class) {
                reader = callback.createReader(Node.class);
                break;
            }
        }

        if (reader == null) {
            throw new XMLBindingException("Could not figure out how to marshal data");
        }
        if (callback.getSOAPStyle() == Style.DOCUMENT
            && callback.getSOAPParameterStyle() == ParameterStyle.WRAPPED) {
            reader.readWrapper(objCtx, isOutBound, xmlNode);
            return;
        }

        Node childNode = NodeUtils.getChildElementNode(xmlNode);

        if (isOutBound && callback.getWebResult() != null) {
            Object retVal = reader.read(callback.getWebResultQName(), -1, childNode);
            objCtx.setReturn(retVal);
            childNode = childNode.getNextSibling();
        }

        WebParam.Mode ignoreParamMode = isOutBound ? WebParam.Mode.IN : WebParam.Mode.OUT;
        int noArgs = callback.getParamsLength();
        Object[] methodArgs = objCtx.getMessageObjects();

        for (int idx = 0; idx < noArgs; idx++) {
            WebParam param = callback.getWebParam(idx);
            if (param.mode() != ignoreParamMode) {
                QName elName = (callback.getSOAPStyle() == Style.DOCUMENT)
                    ? new QName(param.targetNamespace(), param.name())
                    : new QName("", param.partName());

                Object obj = reader.read(elName, idx, childNode);
                if (param.mode() != WebParam.Mode.IN) {
                    try {
                        // TO avoid type safety warning the Holder
                        // needs tobe set as below.
                        methodArgs[idx].getClass().getField("value").set(methodArgs[idx], obj);
                    } catch (Exception ex) {
                        throw new XMLBindingException("Can not set the part value into the Holder field.",
                                                      ex);
                    }
                } else {
                    methodArgs[idx] = obj;
                }
                childNode = childNode.getNextSibling();
            }
        }
    }

    private void addWrapperRoot(XMLMessage xmlMessage, DataBindingCallback callback) throws WSDLException {
        BindingOperation operation = getBindingOperation(callback.getOperationName());
       
        BindingInput input = operation.getBindingInput();

        TBody xmlBinding = null;
        Iterator ite = input.getExtensibilityElements().iterator();
        while (ite.hasNext()) {
            Object obj = ite.next();
            if (obj instanceof TBody) {
                xmlBinding = (TBody)obj;
            }
        }

        if (needRootNode(operation, false)) {
            if (xmlBinding == null || xmlBinding.getRootNode() == null) {
                throw new XMLBindingException("Bare style must define the rootNode in this case!");
            }
            QName rootNode = xmlBinding.getRootNode();
            Document doc = xmlMessage.getRoot();
            String targetNamespace = rootNode.getNamespaceURI() == null
                ? callback.getTargetNamespace() : rootNode.getNamespaceURI();
            Element operationNode = doc.createElementNS(targetNamespace, rootNode.getLocalPart());
            xmlMessage.appendChild(operationNode);
        }
    }

    private void addReturnWrapperRoot(XMLMessage xmlMessage,
                                      DataBindingCallback callback) throws WSDLException {
        BindingOperation operation = getBindingOperation(callback.getOperationName());

        BindingOutput output = operation.getBindingOutput();
        TBody xmlBinding = null;
        Iterator ite = output.getExtensibilityElements().iterator();
        while (ite.hasNext()) {
            Object obj = ite.next();
            if (obj instanceof TBody) {
                xmlBinding = (TBody)obj;
            }
        }
        if (needRootNode(operation, true)) {
            if (xmlBinding == null || xmlBinding.getRootNode() == null) {
                throw new XMLBindingException("Bare style must define the rootNode in this case!");
            }
            QName rootNode = xmlBinding.getRootNode();
            Document doc = xmlMessage.getRoot();
            String targetNamespace = rootNode.getNamespaceURI() == null
                ? callback.getTargetNamespace() : rootNode.getNamespaceURI();
            Element operationNode = doc.createElementNS(targetNamespace, rootNode.getLocalPart());
            xmlMessage.appendChild(operationNode);
        }
    }

    private BindingOperation getBindingOperation(String operationName) throws WSDLException {
        WSDLHelper helper = new WSDLHelper();
        Port port = EndpointReferenceUtils.getPort(this.bus.getWSDLManager(), this.endpointRef);
        return helper.getBindingOperation(port.getBinding(),
                                          operationName);
    }

    private boolean needRootNode(BindingOperation operation, boolean out) {
        WSDLHelper helper = new WSDLHelper();
        Map parts = helper.getParts(operation.getOperation(), out);
        return parts.size() != 1;
    }

    private void addParts(Node xmlNode,
                          ObjectMessageContext objCtx,
                          boolean isOutBound,
                          DataBindingCallback callback) {
        DataWriter<Node> writer = callback.createWriter(Node.class);
        if (writer == null) {
            throw new XMLBindingException("Could not figure out how to marshal data");
        }

        if (callback.getSOAPStyle() == Style.DOCUMENT
            && callback.getSOAPParameterStyle() == ParameterStyle.WRAPPED) {
            writer.writeWrapper(objCtx, isOutBound, xmlNode);
            return;
        }

        // Add the Return Type
        if (isOutBound && callback.getWebResult() != null) {
            writer.write(objCtx.getReturn(), callback.getWebResultQName(), xmlNode);
        }
        // Add the in,inout,out args depend on the inputMode
        WebParam.Mode ignoreParamMode = isOutBound ? WebParam.Mode.IN : WebParam.Mode.OUT;
        int noArgs = callback.getParamsLength();
        Object[] args = objCtx.getMessageObjects();
        for (int idx = 0; idx < noArgs; idx++) {
            WebParam param = callback.getWebParam(idx);
            if (param.mode() != ignoreParamMode) {
                Object partValue = args[idx];
                if (param.mode() != WebParam.Mode.IN) {
                    partValue = ((Holder)args[idx]).value;
                }
           
                QName elName = (callback.getSOAPStyle() == Style.DOCUMENT)
                    ? new QName(param.targetNamespace(), param.name())
                    : new QName("", param.partName());
                writer.write(partValue, elName, xmlNode);
            }
        }
    }
}
TOP

Related Classes of org.objectweb.celtix.bus.bindings.xml.XMLBindingImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.