Package de.danet.an.workflow.tools.soap

Source Code of de.danet.an.workflow.tools.soap.GenericSoapClient

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2004 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: GenericSoapClient.java 2904 2009-01-28 22:21:36Z mlipp $
*
* $Log$
* Revision 1.8  2007/01/30 11:56:15  drmlipp
* Merged Wf-XML branch.
*
* Revision 1.7.4.1  2006/12/20 14:37:59  schnelle
* Implemented Factory GetDefinition.
*
* Revision 1.7  2006/10/17 08:43:42  drmlipp
* Added support for JBoss connection exception detection.
*
* Revision 1.6  2006/09/29 12:32:09  drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.5  2005/09/05 14:03:44  drmlipp
* Adapted to ToolAgent API update.
*
* Revision 1.4  2005/08/29 14:22:32  drmlipp
* Added ConnectException handling for generic soap client.
*
* Revision 1.3  2005/08/04 07:02:37  drmlipp
* Rmoved not needed code.
*
* Revision 1.2  2005/08/03 15:35:35  drmlipp
* Back-ported generic SOAP tool from wfmopen-2 branch.
*
*/
package de.danet.an.workflow.tools.soap;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.ConnectException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;

import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.dom.DOMXPath;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import de.danet.an.util.sax.HandlerStack;
import de.danet.an.util.soap.SOAPBuilder;
import de.danet.an.util.web.W3CDomUtil;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.FormalParameter;
import de.danet.an.workflow.api.SAXEventBuffer;
import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
import de.danet.an.workflow.spis.aii.CannotExecuteException;
import de.danet.an.workflow.spis.aii.ResultProvider;
import de.danet.an.workflow.spis.aii.ToolAgent;
import de.danet.an.workflow.spis.aii.XMLArgumentTypeProvider;
import de.danet.an.workflow.util.SAXEventBufferImpl;
import de.danet.an.workflow.util.XPDLUtil;

/**
* This class provides a generic SOAP client.
*
* @author <a href="mailto:lipp@danet.de">Michael Lipp</a>
* @version $Revision: 2904 $
*/

public class GenericSoapClient
    implements ToolAgent, XMLArgumentTypeProvider, ResultProvider,
               Serializable {

    private static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory.getLog
  (GenericSoapClient.class);

    // hold the mapping of return parameter name and eventually the XPath
    // expression
    private Map returnParamInfo = new HashMap();

    private String endpoint;

    /** The result container. */
    private ThreadLocal result = new ThreadLocal ();

    /**
     * Creates an instance of <code>GenericSoapClient</code>
     * with all attributes initialized to default values.
     */
    public GenericSoapClient () {
    }
   
    /**
     * Get the value of endpoint.
     * @return value of endpoint.
     * @see #setEndpoint
     */
    public String getEndpoint() {
        return endpoint;
    }
   
    /**
     * Set the value of endpoint.
     * @param newEndpoint value to assign to endpoint.
     * @see #getEndpoint
     */
    public void setEndpoint(String newEndpoint) {
        this.endpoint = newEndpoint;
    }

    /**
     * Set the xml definition of output mappings. It is used to convert the
     * WSIF invocation response.
     *
     * @param outputMappings the given xml as W3C Element.
     */
    public void setMappings(Element outputMappings) {
        try {
            // retrieve namespaces
            NodeList namespacesNodeList = outputMappings.getElementsByTagNameNS
    (XPDLUtil.XPDL_EXTN_NS, "Namespaces");
            if (namespacesNodeList.getLength() == 0) {
                namespacesNodeList = outputMappings.getElementsByTagNameNS
                    (XPDLUtil.XPDL_EXTN_V1_1_NS, "Namespaces");
            }
            NodeList nsNodeList = null;
            if (namespacesNodeList.getLength() > 0) {
                Element namespacesNode = (Element)namespacesNodeList.item(0);
                nsNodeList = namespacesNode.getElementsByTagNameNS
        (namespacesNode.getNamespaceURI(), "Namespace");
            }
            NodeList paramNodeList = outputMappings.getElementsByTagNameNS
    (XPDLUtil.XPDL_EXTN_NS, "Parameter");
            if (paramNodeList.getLength() == 0) {
                paramNodeList = outputMappings.getElementsByTagNameNS
                    (XPDLUtil.XPDL_EXTN_V1_1_NS, "Parameter");               
            }
            for (int i = 0; i < paramNodeList.getLength(); i++) {
                Element param = (Element)paramNodeList.item(i);
                String name = param.getAttribute("Name");
                XPath xpath = new DOMXPath (param.getAttribute("Select"));
                if (nsNodeList != null) {
                    for (int j = 0; j < nsNodeList.getLength(); j++) {
                        Element ns = (Element)nsNodeList.item(j);
                        String prefix = ns.getAttribute("Prefix");
                        String uri = ns.getAttribute("Uri");
                        xpath.addNamespace(prefix, uri);
                    }
                }
                returnParamInfo.put(name, xpath);
            }
        } catch (Exception e) {
            // if any error ocurred, outputMappings is still null.
            logger.error("error in setting XML for output mappings!", e);
        }
    }
   
    // Implementation of de.danet.an.workflow.spis.aii.ToolAgent

    /* Comment copied from interface. */
    public void invoke(Activity activity, FormalParameter[] formPars, Map map)
  throws RemoteException, CannotExecuteException {
        try {
            String httpHeaders = (String)map.get("httpHeaders");
            SAXEventBuffer headerContent = (SAXEventBuffer)map.get("header");
            SAXEventBuffer bodyContent = (SAXEventBuffer)map.get("body");
           
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = factory.createConnection();
           
            MessageFactory messageFactory = MessageFactory.newInstance();
            SOAPMessage message = messageFactory.createMessage();
            MimeHeaders mimeHeaders = message.getMimeHeaders();
            SOAPEnvelope env = message.getSOAPPart().getEnvelope();
           
            // Add headers, if any
            if (httpHeaders != null) {
                for (StringTokenizer st
                        = new StringTokenizer(httpHeaders, "\n");
                    st.hasMoreElements();) {
                    String hdr = st.nextToken();
                    int sep = hdr.indexOf(':');
                    if (sep < 0) {
                        throw new CannotExecuteException
                            ("Invalid header (missing ':'): " + hdr);
                    }
                    mimeHeaders.addHeader
                        (hdr.substring(0, sep),
                         hdr.substring(sep + 1).trim());
                }
            }

            // Add header content, if any
            if (headerContent != null) {
                SOAPHeader hdr = env.getHeader();
                appendNodes (env, hdr, headerContent);
            }

            // Add body content
            SOAPBody body = env.getBody();
            appendNodes (env, body, bodyContent);
           
            // Now invoke with the created message
            SOAPMessage response = null;
            try {
                response = connection.call(message, new URL(endpoint));
            } catch (SOAPException e) {
                if (e.getMessage().indexOf("ConnectException") >= 0) {
                    // Axis way of reporting this
                    if (logger.isDebugEnabled()) {
                        logger.debug
          ("Cannot invoke (signalled ConnectException): "
           + e.getMessage (), e);
                    }
                    throw new CannotExecuteException
                        ("Assuming connection failure: " + e.getMessage(),
                         new ConnectException (e.getMessage(), e));
                } else if (e.getCause() != null
                           && e.getCause().getCause() != null
                           && (e.getCause().getCause()
                               instanceof java.net.ConnectException)) {
                    // JBossWS way of reporting this
                    throw new CannotExecuteException
                        ("Assuming connection failure: " + e.getMessage(),
                         new ConnectException (e.getMessage(), e));
                }
                throw e;
            } finally {
                connection.close ();
            }
            SOAPPart respPart = response.getSOAPPart ();
           
            Map resData = new HashMap ();
            for (int i = 0; i < formPars.length; i++) {
                if (formPars[i].mode() == FormalParameter.Mode.IN) {
                    continue;
                }
                XPath path = (XPath)returnParamInfo.get(formPars[i].id());
                if (path == null) {
                    resData.put(formPars[i].id(),
        convertToSax(respPart.getDocumentElement()));
                } else {
                    if (formPars[i].type().equals (String.class)) {
                        resData.put(formPars[i].id(),
            path.stringValueOf(respPart));
                    } else if ((formPars[i].type() instanceof Class)
             && Number.class.isAssignableFrom
             ((Class)formPars[i].type())) {
                        Number n = path.numberValueOf(respPart);
                        if (formPars[i].type().equals (Long.class)
          && !(n instanceof Long)) {
                            n = new Long (n.longValue());
                        }
                        resData.put(formPars[i].id(), n);
                    } else {
                        resData.put(formPars[i].id(),
            convertToSax(path.selectNodes(respPart)));
                    }
                }
            }     
            result.set (resData);
        } catch (CannotExecuteException e) {
            throw e;
        } catch (MalformedURLException e) {
            throw new CannotExecuteException (e.getMessage(), e);
        } catch (SOAPException e) {
            throw new CannotExecuteException (e.getMessage(), e);
        } catch (SAXException e) {
            throw new CannotExecuteException (e.getMessage(), e);
        } catch (JaxenException e) {
            throw new CannotExecuteException (e.getMessage(), e);
        } catch (TransformerException e) {
            throw new CannotExecuteException (e.getMessage(), e);
        }
    }

    private SAXEventBuffer convertToSax (Node value)
        throws TransformerException {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        SAXEventBufferImpl res = new SAXEventBufferImpl ();
        t.transform (new DOMSource(value), new SAXResult (res));
        return res;
    }

    private SAXEventBuffer convertToSax(List nodes)
        throws TransformerException {
        Document doc = W3CDomUtil.createNewDocument();
        DocumentFragment frag = doc.createDocumentFragment();
        for (Iterator i = nodes.iterator(); i.hasNext();) {
            Element e = (Element) i.next();
            frag.appendChild(doc.importNode(e, true));
        }
        return convertToSax(frag);
    }

    private void appendNodes
    (SOAPEnvelope env, SOAPElement root, SAXEventBuffer data)
    throws SAXException {
        HandlerStack hs = new HandlerStack (new SOAPBuilder (root));
        hs.setContextData ("envelope", env);
        data.emit(hs.contentHandler());
    }

    /**
     * Return the requested type for XML arguments.
     * @return one of <code>XML_AS_W3C_DOM</code>,
     * <code>XML_AS_JDOM</code> or <code>XML_AS_SAX</code>
     */
    public int requestedXMLArgumentType () {
        return XMLArgumentTypeProvider.XML_AS_SAX;
    }

    /**
     * Return the result evaluated during {@link ToolAgent#invoke
     * <code>invoke</code>}. The method will only be called once after
     * each invoke, i.e. the attribute holding the result be be
     * cleared in this method.
     *
     * @return the result data or <code>null</code> if the invocation
     * does not return any data.
     */
    public Object result () {
        Object res = result.get();
        result.set (null);
        return res;
    }

    /* Comment copied from interface. */
    public void terminate(Activity activity)
    throws ApplicationNotStoppedException {
        throw new ApplicationNotStoppedException
        ("Terminate not implemented for GenericSoapClient.");
    }
}
TOP

Related Classes of de.danet.an.workflow.tools.soap.GenericSoapClient

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