/*
 * Copyright (c) 1998, 2020 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.internal.dbws;

//javase imports

import static jakarta.xml.soap.SOAPConstants.SOAP_1_2_PROTOCOL;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE;
import static jakarta.xml.ws.handler.MessageContext.INBOUND_MESSAGE_ATTACHMENTS;
import static org.eclipse.persistence.internal.dbws.SOAPResponseWriter.RECEIVER_QNAME;
import static org.eclipse.persistence.internal.dbws.SOAPResponseWriter.SERVER_QNAME;
import static org.eclipse.persistence.internal.xr.Util.DBWS_SCHEMA_XML;
import static org.eclipse.persistence.internal.xr.Util.DBWS_SERVICE_XML;
import static org.eclipse.persistence.internal.xr.Util.DBWS_WSDL;
import static org.eclipse.persistence.internal.xr.Util.META_INF_PATHS;
import static org.eclipse.persistence.internal.xr.Util.SCHEMA_2_CLASS;
import static org.eclipse.persistence.internal.xr.Util.SERVICE_NAMESPACE_PREFIX;
import static org.eclipse.persistence.internal.xr.Util.WEB_INF_DIR;
import static org.eclipse.persistence.internal.xr.Util.WSDL_DIR;
import static org.eclipse.persistence.oxm.mappings.UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import jakarta.activation.DataHandler;
import jakarta.servlet.ServletContext;
import javax.xml.namespace.QName;
import jakarta.xml.soap.SOAPBodyElement;
import jakarta.xml.soap.SOAPElement;
import jakarta.xml.soap.SOAPEnvelope;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPFactory;
import jakarta.xml.soap.SOAPFault;
import jakarta.xml.soap.SOAPMessage;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import jakarta.xml.ws.Provider;
import jakarta.xml.ws.WebServiceException;
import jakarta.xml.ws.handler.MessageContext;
import jakarta.xml.ws.soap.SOAPFaultException;

import org.eclipse.persistence.dbws.DBWSModelProject;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DBWSException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.xr.Invocation;
import org.eclipse.persistence.internal.xr.Operation;
import org.eclipse.persistence.internal.xr.Parameter;
import org.eclipse.persistence.internal.xr.ValueObject;
import org.eclipse.persistence.internal.xr.XRServiceAdapter;
import org.eclipse.persistence.internal.xr.XRServiceFactory;
import org.eclipse.persistence.internal.xr.XRServiceModel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.attachment.XMLAttachmentUnmarshaller;
import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.sessions.Project;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

// Java extension imports
// EclipseLink imports

/**
 * <p>
 * <b>INTERNAL:</b> ProviderHelper bridges between {@link DBWSAdapter}'s and JAX-WS {@link Provider}'s
 * <p>
 *
 * @author Mike Norman - michael.norman@oracle.com
 * @since EclipseLink 1.1
 * <pre>
 * packaging required for deployment as a Web Service
 * \--- root of war file
 *      |
 *      \---web-inf
 *          |   web.xml
 *          |
 *          +---classes
 *          |   +---META-INF
 *          |   |    eclipselink-dbws.xml
 *          |   |    eclipselink-dbws-sessions.xml -- name can be overridden by &lt;sessions-file&gt; entry in eclipselink-dbws.xml
 *          |   |    eclipselink-dbws-or.xml
 *          |   |    eclipselink-dbws-ox.xml
 *          |   |
 *          |   +---_dbws
 *          |   |    DBWSProvider.java         -- (source provided as a convenience for IDE integration)
 *          |   |    DBWSProvider.class        -- ASM-generated jakarta.xml.ws.Provider
 *          |   |
 *          |   \---foo                        -- optional domain classes
 *          |       \---bar
 *          |             Address.class
 *          |             Employee.class
 *          |             PhoneNumber.class
 *          \---wsdl
 *                 swaref.xsd                  -- optional to handle attachments
 *                 eclipselink-dbws.wsdl
 *                 eclipselink-dbws-schema.xsd
 * </pre>
 */
public class ProviderHelper extends XRServiceFactory {
    public static final QName SENDER_QNAME = new QName(URI_NS_SOAP_1_2_ENVELOPE, "Sender");
    public static final QName CLIENT_QNAME = new QName(URI_NS_SOAP_1_1_ENVELOPE, "Client");

    protected static final String XSL_PREAMBLE =
      "<?xml version=\"1.0\"?> " +
      "<xsl:stylesheet " +
        "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\" " +
        "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
        "xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" " +
        "> " +
      "<xsl:output method=\"xml\" encoding=\"UTF-8\"/> ";
    protected static final String XSL_POSTSCRIPT = "</xsl:stylesheet>";
    public static final String MATCH_SCHEMA =
      XSL_PREAMBLE +
        "<xsl:template match=\"/\">" +
             "<xsl:apply-templates/>" +
        "</xsl:template>" +
        "<xsl:template match=\"//xsd:schema\">" +
          "<xsl:copy-of select=\".\"/>" +
        "</xsl:template>" +
      XSL_POSTSCRIPT;
    public SOAPResponseWriter responseWriter = null;
    protected boolean mtomEnabled;
    protected MessageContext mc;

    // Default constructor required by servlet/jax-ws spec
    public ProviderHelper() {
        super();
    }

    protected void setMessageContext(MessageContext mc) {
        this.mc = mc;
    }

    protected InputStream initXRServiceStream(ClassLoader parentClassLoader,
        @SuppressWarnings("unused") ServletContext sc) {
        InputStream xrServiceStream = null;
        for (String searchPath : META_INF_PATHS) {
            String path = searchPath + DBWS_SERVICE_XML;
            xrServiceStream = parentClassLoader.getResourceAsStream(path);
            if (xrServiceStream != null) {
                break;
            }
        }
        if (xrServiceStream == null) {
            throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_SERVICE_XML));
        }
        return xrServiceStream;
    }

    protected InputStream initXRSchemaStream(ClassLoader parentClassLoader, ServletContext sc) {
        InputStream xrSchemaStream = null;
        String path = WSDL_DIR + DBWS_SCHEMA_XML;
        if (sc != null) {
            path = "/" + WEB_INF_DIR + path;
            xrSchemaStream = sc.getResourceAsStream(path);
        }
        else {
            // if ServletContext is null, then we are running in JavaSE6 'container-less' mode
            xrSchemaStream = parentClassLoader.getResourceAsStream(path);
        }
        if (xrSchemaStream == null) {
            throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_SCHEMA_XML));
        }
        return xrSchemaStream;
    }

    protected InputStream initWSDLInputStream(ClassLoader parentClassLoader, ServletContext sc) {
        InputStream wsdlInputStream = null;
        String path = WSDL_DIR + DBWS_WSDL;
        if (sc != null) {
            path = "/" + WEB_INF_DIR + path;
            wsdlInputStream = sc.getResourceAsStream(path);
        }
        else {
            // if ServletContext is null, then we are running in JavaSE6 'container-less' mode
            wsdlInputStream = parentClassLoader.getResourceAsStream(path);
        }
        if (wsdlInputStream == null) {
            throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_WSDL));
        }
        return wsdlInputStream;
    }

    @SuppressWarnings("unchecked")
    public void init(ClassLoader parentClassLoader, ServletContext sc, boolean mtomEnabled) {
        this.parentClassLoader = parentClassLoader;
        this.mtomEnabled = mtomEnabled;

        InputStream xrServiceStream = initXRServiceStream(parentClassLoader, sc);
        DBWSModelProject xrServiceModelProject = new DBWSModelProject();
        XMLContext xmlContext = new XMLContext(xrServiceModelProject);
        XMLUnmarshaller unmarshaller = xmlContext.createUnmarshaller();
        XRServiceModel xrServiceModel;
        try {
            xrServiceModel = (XRServiceModel)unmarshaller.unmarshal(xrServiceStream);
        }
        catch (XMLMarshalException e) {
            // something went wrong parsing the eclipselink-dbws.xml - can't recover from that
            throw new WebServiceException(DBWSException.couldNotParseDBWSFile());
        }
        finally {
            try {
                xrServiceStream.close();
            }
            catch (IOException e) {
                // ignore
            }
        }

        xrSchemaStream = initXRSchemaStream(parentClassLoader, sc);
        try {
            buildService(xrServiceModel); // inherit xrService processing from XRServiceFactory
        }
        catch (Exception e) {
            // something went wrong building the service
            throw new WebServiceException(e);
        }

        // the xrService built by 'buildService' above is overridden to produce an
        // instance of DBWSAdapter (a sub-class of XRService)
        DBWSAdapter dbwsAdapter = (DBWSAdapter)xrService;

        // get inline schema from WSDL - has additional types for the operations
        try (InputStream wsdlInputStream = initWSDLInputStream(parentClassLoader, sc)) {
            StringWriter sw = new StringWriter();
            StreamSource wsdlStreamSource = new StreamSource(wsdlInputStream);
            Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(
                new StringReader(MATCH_SCHEMA)));
            StreamResult streamResult = new StreamResult(sw);
            t.transform(wsdlStreamSource, streamResult);
            SchemaModelProject schemaProject = new SchemaModelProject();
            XMLContext xmlContext2 = new XMLContext(schemaProject);
            unmarshaller = xmlContext2.createUnmarshaller();
            Schema extendedSchema = (Schema)unmarshaller.unmarshal(new StringReader(sw.toString()));
            dbwsAdapter.setExtendedSchema(extendedSchema);
        } catch (IOException | TransformerException e) {
            // that's Ok, WSDL may not contain inline schema
            xmlContext.getSession().getSessionLog().log(
                    SessionLog.FINE, SessionLog.DBWS, "dbws_no_wsdl_inline_schema", e.getLocalizedMessage());
        }

        // an Invocation needs a mapping for its parameters - use XMLAnyCollectionMapping +
        // custom AttributeAccessor
        // NB - this code is NOt in it own initNNN method, cannot be overridden
        String tns = dbwsAdapter.getExtendedSchema().getTargetNamespace();
        Project oxProject = dbwsAdapter.getOXSession().getProject();
        XMLDescriptor invocationDescriptor = new XMLDescriptor();
        invocationDescriptor.setJavaClass(Invocation.class);
        NamespaceResolver nr = new NamespaceResolver();
        invocationDescriptor.setNamespaceResolver(nr);
        nr.put(SERVICE_NAMESPACE_PREFIX, tns);
        nr.setDefaultNamespaceURI(tns);
        XMLAnyCollectionMapping parametersMapping = new XMLAnyCollectionMapping();
        parametersMapping.setAttributeName("parameters");
        parametersMapping.setAttributeAccessor(new AttributeAccessor() {
            Project oxProject;
            DBWSAdapter dbwsAdapter;
            @Override
            public Object getAttributeValueFromObject(Object object) {
              return ((Invocation)object).getParameters();
            }
            @Override
            public void setAttributeValueInObject(Object object, Object value) {
                Invocation invocation = (Invocation)object;
                Vector<Object> values = (Vector<Object>)value;
                for (Iterator<Object> i = values.iterator(); i.hasNext();) {
                  /* scan through values:
                   *  if XML conforms to something mapped, it an object; else it is a DOM Element
                   *  (probably a scalar). Walk through operations for the types, converting
                   *   as required. The 'key' is the local name of the element - for mapped objects,
                   *   have to get the element name from the schema context for the object
                   */
                  Object o = i.next();
                  if (o instanceof Element) {
                    Element e = (Element)o;
                    String key = e.getLocalName();
                    if ("theInstance".equals(key)) {
                        NodeList nl = e.getChildNodes();
                        for (int j = 0; j < nl.getLength(); j++) {
                            Node n = nl.item(j);
                            if (n.getNodeType() == Node.ELEMENT_NODE) {
                                try {
                                    Object theInstance =
                                        dbwsAdapter.getXMLContext().createUnmarshaller().unmarshal(n);
                                    if (theInstance instanceof XMLRoot) {
                                        theInstance = ((XMLRoot)theInstance).getObject();
                                    }
                                    invocation.setParameter(key, theInstance);
                                    break;
                                }
                                catch (XMLMarshalException xmlMarshallException) {
                                   throw new WebServiceException(xmlMarshallException);
                                }
                            }
                        }
                    }
                    else {
                        ClassDescriptor desc = null;
                        for (ClassDescriptor xdesc : oxProject.getOrderedDescriptors()) {
                            XMLSchemaReference schemaReference = xdesc instanceof XMLDescriptor
                                    ? ((XMLDescriptor)xdesc).getSchemaReference() : null;
                            if (schemaReference != null && schemaReference.getSchemaContext().equalsIgnoreCase(key)) {
                                desc = xdesc;
                                break;
                            }
                        }
                        if (desc != null) {
                            try {
                                Object theObject =
                                    dbwsAdapter.getXMLContext().createUnmarshaller().unmarshal(e,
                                        desc.getJavaClass());
                                if (theObject instanceof XMLRoot) {
                                    theObject = ((XMLRoot)theObject).getObject();
                                }
                                invocation.setParameter(key, theObject);
                            }
                            catch (XMLMarshalException xmlMarshallException) {
                               throw new WebServiceException(xmlMarshallException);
                            }
                        }
                        else {
                            String serviceName = e.getParentNode().getLocalName();
                            boolean found = false;
                            for (Operation op : dbwsAdapter.getOperationsList()) {
                                if (op.getName().equals(serviceName)) {
                                    for (Parameter p : op.getParameters()) {
                                        if (p.getName().equals(key)) {
                                            desc = dbwsAdapter.getDescriptorsByQName().get(p.getType());
                                            if (desc != null) {
                                                found = true;
                                            }
                                            break;
                                        }
                                    }
                                }
                                if (found) {
                                    break;
                                }
                            }
                            if (found) {
                                Object theObject =
                                    dbwsAdapter.getXMLContext().createUnmarshaller().unmarshal(e,
                                        desc.getJavaClass());
                                if (theObject instanceof XMLRoot) {
                                    theObject = ((XMLRoot)theObject).getObject();
                                }
                                invocation.setParameter(key, theObject);
                            }
                            else {
                                // cant use e.getTextContent() - some DOM impls dont support it :-(
                                //String val = e.getTextContent();
                                StringBuilder sb = new StringBuilder();
                                NodeList childNodes = e.getChildNodes();
                                for(int idx=0; idx < childNodes.getLength(); idx++ ) {
                                    if (childNodes.item(idx).getNodeType() == Node.TEXT_NODE ) {
                                        sb.append(childNodes.item(idx).getNodeValue());
                                    }
                                }
                                invocation.setParameter(key, sb.toString());
                            }
                        }
                    }
                  }
                  else {
                    XMLDescriptor descriptor = (XMLDescriptor)oxProject.getDescriptor(o.getClass());
                    String key = descriptor.getDefaultRootElement();
                    int idx = key.indexOf(':');
                    if (idx != -1) {
                      key = key.substring(idx+1);
                    }
                    invocation.setParameter(key, o);
                  }
                }
            }
            public AttributeAccessor setProjectAndAdapter(Project oxProject, DBWSAdapter dbwsAdapter) {
              this.oxProject = oxProject;
              this.dbwsAdapter = dbwsAdapter;
              return this;
            }
        }.setProjectAndAdapter(oxProject, dbwsAdapter));
        parametersMapping.setKeepAsElementPolicy(KEEP_UNKNOWN_AS_ELEMENT);
        invocationDescriptor.addMapping(parametersMapping);
        oxProject.addDescriptor(invocationDescriptor);
        ((DatabaseSessionImpl)dbwsAdapter.getOXSession()).initializeDescriptorIfSessionAlive(invocationDescriptor);
        dbwsAdapter.getXMLContext().storeXMLDescriptorByQName(invocationDescriptor);

        // create SOAP message response handler of appropriate version
        responseWriter = new SOAPResponseWriter(dbwsAdapter);
        responseWriter.initialize();
    }

    @SuppressWarnings({"unchecked"})
    public SOAPMessage invoke(SOAPMessage request) {
        Map<String,DataHandler> attachments = null;
        if (mtomEnabled) {
            attachments = (Map<String, DataHandler>)mc.get(INBOUND_MESSAGE_ATTACHMENTS);
        }
        SOAPMessage response = null;
        boolean usesSOAP12 = false;
        DBWSAdapter dbwsAdapter = (DBWSAdapter)xrService;

        SOAPEnvelope envelope = null;
        try {
            envelope = request.getSOAPPart().getEnvelope();
        }
        catch (SOAPException se) {
            throw new WebServiceException(se.getMessage(), se);
        }
        // check soap 1.2 Namespace in envelope
        String namespaceURI = envelope.getNamespaceURI();
        usesSOAP12 = namespaceURI.equals(URI_NS_SOAP_1_2_ENVELOPE);

        SOAPElement body;
        try {
            body = getSOAPBodyElement(envelope);
        }
        catch (SOAPException se) {
            throw new WebServiceException(se.getMessage(), se);
        }

        if (body == null) {
            SOAPFault soapFault = null;
            try {
                SOAPFactory soapFactory = null;
                if (usesSOAP12) {
                    soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                } else {
                    soapFactory = SOAPFactory.newInstance();
                }
                QName faultCodeQName = null;
                if (usesSOAP12) {
                    faultCodeQName = SENDER_QNAME;
                } else {
                    faultCodeQName = CLIENT_QNAME;
                }
                soapFault = soapFactory.createFault("SOAPMessage request format error - missing body element", faultCodeQName);
            } catch (SOAPException se) {
                throw new WebServiceException(se.getMessage(), se);
            }
            throw new SOAPFaultException(soapFault);
        }

        XMLRoot xmlRoot = null;
        try {
            XMLContext xmlContext = dbwsAdapter.getXMLContext();
            XMLUnmarshaller unmarshaller = xmlContext.createUnmarshaller();
            if (attachments != null && attachments.size() > 0) {
                unmarshaller.setAttachmentUnmarshaller(new XMLAttachmentUnmarshaller() {
                    Map<String,DataHandler> attachments;
                    public XMLAttachmentUnmarshaller setAttachments(Map<String, DataHandler> attachments) {
                        this.attachments = attachments;
                        return this;
                    }
                    @Override
                    public boolean isXOPPackage() {
                        return true;
                    }
                    @Override
                    public DataHandler getAttachmentAsDataHandler(String id) {
                        // strip off 'cid:' (Is this needed?)
                        String attachmentRefId = id;
                        if (attachmentRefId.startsWith("cid:")) {
                            attachmentRefId = attachmentRefId.substring(4);
                        }
                        return attachments.get(attachmentRefId);
                    }
                    @Override
                    public byte[] getAttachmentAsByteArray(String id) {
                        ByteArrayOutputStream out = null;
                        try {
                            DataHandler dh = attachments.get(id);
                            if (dh == null) {
                                return null;
                            }
                            InputStream in = dh.getInputStream();
                            out = new ByteArrayOutputStream(1024);
                            byte[] buf = new byte[1024];
                            int len;
                            while ((len = in.read(buf)) > 0) {
                              out.write(buf, 0, len);
                            }
                        }
                        catch (IOException e) {
                            // e.printStackTrace();
                        }
                        if (out != null) {
                            return out.toByteArray();
                        }
                        return null;
                    }
                }.setAttachments(attachments));
                dbwsAdapter.setCurrentAttachmentUnmarshaller(unmarshaller.getAttachmentUnmarshaller());
            }
            xmlRoot = (XMLRoot)unmarshaller.unmarshal(body, Invocation.class);
        }
        catch (Exception e) {
            SOAPFault soapFault = null;
            try {
                SOAPFactory soapFactory = null;
                if (usesSOAP12) {
                    soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                } else {
                    soapFactory = SOAPFactory.newInstance();
                }
                QName faultCodeQName = null;
                if (usesSOAP12) {
                    faultCodeQName = SENDER_QNAME;
                } else {
                    faultCodeQName = CLIENT_QNAME;
                }
                Throwable e1 = e;
                if (e.getCause() != null) {
                    e1 = e.getCause();
                }
                soapFault = soapFactory.createFault("SOAPMessage request format error - " + e1, faultCodeQName);
            } catch (SOAPException se) {
                throw new WebServiceException(se.getMessage(), se);
            }
            throw new SOAPFaultException(soapFault);
        }

        Invocation invocation = (Invocation)xmlRoot.getObject();
        invocation.setName(xmlRoot.getLocalName());
        Operation op = dbwsAdapter.getOperation(invocation.getName());
        /*
         * Fix up types for arguments - scan the extended schema for the operation's Request type.
         *
         * For most parameters, the textual node content is fine, but for date/time and
         * binary objects, we must convert
         */
        org.eclipse.persistence.internal.oxm.schema.model.Element invocationElement =
          (org.eclipse.persistence.internal.oxm.schema.model.Element)
           dbwsAdapter.getExtendedSchema().getTopLevelElements().get(invocation.getName());
        String typeName = invocationElement.getType();
        int idx = typeName.indexOf(':');
        if (idx != -1) {
          // strip-off any namespace prefix
          typeName = typeName.substring(idx+1);
        }
        ComplexType complexType =
          (ComplexType)dbwsAdapter.getExtendedSchema().getTopLevelComplexTypes().get(typeName);
        if (complexType.getSequence() != null) {
            // for each operation, there is a corresponding top-level Request type
            // which has the arguments to the operation
            for (Iterator<org.eclipse.persistence.internal.oxm.schema.model.Element> i
                    = complexType.getSequence().getOrderedElements().iterator();
                    i .hasNext();) {
              org.eclipse.persistence.internal.oxm.schema.model.Element e = i.next();
              String argName = e.getName();
              Object argValue = invocation.getParameter(argName);
              String argType = e.getType();
              if (argType != null) {
                 String argTypePrefix = null;
                 String nameSpaceURI = null;
                 idx = argType.indexOf(':');
                 if (idx != -1) {
                   argTypePrefix = argType.substring(0,idx);
                   argType = argType.substring(idx+1);
                   nameSpaceURI =
                     dbwsAdapter.getSchema().getNamespaceResolver().resolveNamespacePrefix(argTypePrefix);
                 }
                 QName argQName = argTypePrefix == null ? new QName(nameSpaceURI, argType) :
                     new QName(nameSpaceURI, argType, argTypePrefix);
                 Class<?> clz = SCHEMA_2_CLASS.get(argQName);
                 if (clz != null) {
                   argValue = ((XMLConversionManager)dbwsAdapter.getOXSession().getDatasourcePlatform().
                     getConversionManager()).convertObject(argValue, clz, argQName);
                   invocation.setParameter(argName, argValue);
                 }
              }
              // incoming attachments ?
            }
        }
        Object result = null;
        try {
            result = op.invoke(dbwsAdapter, invocation);
            if (result instanceof ValueObject) {
                result = ((ValueObject)result).value;
            }
            response = responseWriter.generateResponse(op, usesSOAP12, result);
        }
        catch (SOAPException se) {
            throw new WebServiceException(se.getMessage(), se);
        }
        catch (Exception e) {
            try {
                response = responseWriter.generateResponse(op, usesSOAP12, e);
            }
            catch (SOAPException soape1) {
                SOAPFault soapFault = null;
                try {
                    SOAPFactory soapFactory = null;
                    if (usesSOAP12) {
                        soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                    } else {
                        soapFactory = SOAPFactory.newInstance();
                    }
                    QName faultCodeQName = null;
                    if (usesSOAP12) {
                        faultCodeQName = RECEIVER_QNAME;
                    } else {
                        faultCodeQName = SERVER_QNAME;
                    }
                    soapFault = soapFactory.createFault("SOAPMessage response error - " + e.getMessage(), faultCodeQName);
                } catch (SOAPException soape2) {
                    throw new WebServiceException(soape2.getMessage(), soape2);
                }
                throw new SOAPFaultException(soapFault);
            }
        }
        return response;
    }

    public void destroy() {
        logoutSessions();
        responseWriter = null;
        try {
            xrSchemaStream.close();
        }
        catch (IOException ioe) {
            /* safe to ignore */
        }
        xrSchemaStream = null;
        parentClassLoader = null;
        xrService.setXMLContext(null);
        xrService = null;
    }

    @Override
    public XRServiceAdapter buildService(XRServiceModel xrServiceModel) {
        xrService = new DBWSAdapter(); // use subclass to hold extended WSDL schema
        DBWSAdapter dbws = (DBWSAdapter)xrService;
        dbws.setName(xrServiceModel.getName());
        dbws.setSessionsFile(xrServiceModel.getSessionsFile());
        dbws.setOperations(xrServiceModel.getOperations());
        initializeService(parentClassLoader, xrSchemaStream);
        return dbws;
    }

    public static SOAPElement getSOAPBodyElement(SOAPEnvelope envelope) throws SOAPException {
        for (@SuppressWarnings("rawtypes")
        Iterator it = envelope.getBody().getChildElements(); it.hasNext();) {
            Object node = it.next();
            if (node instanceof SOAPBodyElement) {
                return (SOAPElement) node;
            }
        }
        return null;
    }
}
