/*
 * 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 = 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;
    }
}
