/*
 * 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.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
 *
 * @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;
        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;
        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;
        boolean usesSOAP12;
        DBWSAdapter dbwsAdapter = (DBWSAdapter)xrService;

        SOAPEnvelope envelope;
        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;
            try {
                SOAPFactory soapFactory;
                if (usesSOAP12) {
                    soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                } else {
                    soapFactory = SOAPFactory.newInstance();
                }
                QName faultCodeQName;
                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;
        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;
            try {
                SOAPFactory soapFactory;
                if (usesSOAP12) {
                    soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                } else {
                    soapFactory = SOAPFactory.newInstance();
                }
                QName faultCodeQName;
                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;
        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;
                try {
                    SOAPFactory soapFactory;
                    if (usesSOAP12) {
                        soapFactory = SOAPFactory.newInstance(SOAP_1_2_PROTOCOL);
                    } else {
                        soapFactory = SOAPFactory.newInstance();
                    }
                    QName faultCodeQName;
                    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;
    }
}
