org.apache.taverna.activities.wsdl.T2WSDLSOAPInvoker.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.taverna.activities.wsdl.T2WSDLSOAPInvoker.java

Source

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.taverna.activities.wsdl;

import com.fasterxml.jackson.databind.JsonNode;
import java.io.StringReader;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;

import org.apache.taverna.security.credentialmanager.CMException;
import org.apache.taverna.security.credentialmanager.CredentialManager;
import org.apache.taverna.security.credentialmanager.UsernamePassword;
import org.apache.taverna.wsdl.parser.WSDLParser;
import org.apache.taverna.wsdl.soap.WSDLSOAPInvoker;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Invokes SOAP based Web Services from T2.
 * 
 * Subclasses WSDLSOAPInvoker used for invoking Web Services from Taverna 1.x
 * and extends it to provide support for invoking secure Web services.
 * 
 * @author Stuart Owen
 * @author Alex Nenadic
 * @author Stian Soiland-Reyes
 * 
 */
public class T2WSDLSOAPInvoker extends WSDLSOAPInvoker {

    private static final String REFERENCE_PROPERTIES = "ReferenceProperties";
    private static final String ENDPOINT_REFERENCE = "EndpointReference";
    private static Logger logger = Logger.getLogger(T2WSDLSOAPInvoker.class);

    private static final String WSA200403NS = "http://schemas.xmlsoap.org/ws/2004/03/addressing";

    private String wsrfEndpointReference = null;

    private CredentialManager credentialManager;

    public T2WSDLSOAPInvoker(WSDLParser parser, String operationName, List<String> outputNames,
            CredentialManager credentialManager) {
        super(parser, operationName, outputNames);
        this.credentialManager = credentialManager;
    }

    public T2WSDLSOAPInvoker(WSDLParser parser, String operationName, List<String> outputNames,
            String wsrfEndpointReference, CredentialManager credentialManager) {
        this(parser, operationName, outputNames, credentialManager);
        this.wsrfEndpointReference = wsrfEndpointReference;

        //                if (wsrfEndpointReference != null && 
        //                    parser.isWSRFOperation(operationName) == null) {
        //                    logger.warn("not a WSRF operation: " + operationName);
        //                } else {
        //                    this.wsrfEndpointReference = wsrfEndpointReference;
        //                }
    }

    //   protected void configureSecurity(Call call,
    //         WSDLActivityConfigurationBean bean) throws Exception {
    //
    //      // If security settings require WS-Security - configure the axis call
    //      // with appropriate properties
    //      String securityProfile = bean.getSecurityProfile();
    //      if (securityProfile
    //            .equals(SecurityProfiles.WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD)
    //            || securityProfile
    //                  .equals(SecurityProfiles.WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD)
    //            || securityProfile
    //                  .equals(SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_PLAINTEXTPASSWORD)
    //            || securityProfile
    //                  .equals(SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD)) {
    //         
    //         UsernamePassword usernamePassword = getUsernameAndPasswordForService(bean, false);
    //         call.setProperty(Call.USERNAME_PROPERTY, usernamePassword.getUsername());
    //         call.setProperty(Call.PASSWORD_PROPERTY, usernamePassword.getPasswordAsString());
    //         usernamePassword.resetPassword();
    //      } else if (securityProfile.equals(SecurityProfiles.HTTP_BASIC_AUTHN)){
    //         // Basic HTTP AuthN - set HTTP headers
    //         // pathrecursion allowed
    //         UsernamePassword usernamePassword = getUsernameAndPasswordForService(bean, true);
    //         MessageContext context = call.getMessageContext();
    //         context.setUsername(usernamePassword.getUsername());
    //         context.setPassword(usernamePassword.getPasswordAsString());
    //         usernamePassword.resetPassword();
    //      } else {
    //         logger.error("Unknown security profile " + securityProfile);
    //      }
    //   }

    /**
     * Get username and password from Credential Manager or ask user to supply
     * one. Username is the first element of the returned array, and the
     * password is the second.
     */
    protected UsernamePassword getUsernameAndPasswordForService(JsonNode configurationBean,
            boolean usePathRecursion) throws CMException {

        // Try to get username and password for this service from Credential
        // Manager (which should pop up UI if needed)
        URI serviceUri = URI.create(configurationBean.get("operation").get("wsdl").textValue());
        UsernamePassword username_password = credentialManager.getUsernameAndPasswordForService(serviceUri,
                usePathRecursion, null);
        if (username_password == null) {
            throw new CMException("No username/password provided for service " + serviceUri);
        }
        return username_password;
    }

    @Override
    protected void addSoapHeader(SOAPEnvelope envelope) throws SOAPException {
        if (wsrfEndpointReference != null) {

            // Extract elements
            // Add WSA-stuff
            // Add elements

            Document wsrfDoc;
            try {
                wsrfDoc = parseWsrfEndpointReference(wsrfEndpointReference);
            } catch (Exception e) {
                logger.warn("Could not parse endpoint reference, ignoring:\n" + wsrfEndpointReference, e);
                return;
            }

            Element wsrfRoot = wsrfDoc.getDocumentElement();

            Element endpointRefElem = null;
            if (!wsrfRoot.getNamespaceURI().equals(WSA200403NS)
                    || !wsrfRoot.getLocalName().equals(ENDPOINT_REFERENCE)) {
                // Only look for child if the parent is not an EPR
                NodeList nodes = wsrfRoot.getChildNodes();
                for (int i = 0, n = nodes.getLength(); i < n; i++) {
                    Node node = nodes.item(i);
                    if (Node.ELEMENT_NODE == node.getNodeType() && node.getLocalName().equals(ENDPOINT_REFERENCE)
                            && node.getNamespaceURI().equals(WSA200403NS)) {
                        // Support wrapped endpoint reference for backward compatibility
                        // and convenience (T2-677)
                        endpointRefElem = (Element) node;
                        break;
                    }
                }
            }

            if (endpointRefElem == null) {
                logger.warn("Unexpected element name for endpoint reference, but inserting anyway: "
                        + wsrfRoot.getTagName());
                endpointRefElem = wsrfRoot;
            }

            Element refPropsElem = null;
            NodeList nodes = endpointRefElem.getChildNodes();
            for (int i = 0, n = nodes.getLength(); i < n; i++) {
                Node node = nodes.item(i);
                if (Node.ELEMENT_NODE == node.getNodeType() && node.getLocalName().equals(REFERENCE_PROPERTIES)
                        && node.getNamespaceURI().equals(WSA200403NS)) {
                    refPropsElem = (Element) node;
                    break;
                }
            }
            if (refPropsElem == null) {
                logger.warn("Could not find " + REFERENCE_PROPERTIES);
                return;
            }

            SOAPHeader header = envelope.getHeader();
            if (header == null) {
                header = envelope.addHeader();
            }

            NodeList refProps = refPropsElem.getChildNodes();

            for (int i = 0, n = refProps.getLength(); i < n; i++) {
                Node node = refProps.item(i);

                if (Node.ELEMENT_NODE == node.getNodeType()) {
                    SOAPElement soapElement = SOAPFactory.newInstance().createElement((Element) node);
                    header.addChildElement(soapElement);

                    Iterator<SOAPHeaderElement> headers = header.examineAllHeaderElements();
                    while (headers.hasNext()) {
                        SOAPHeaderElement headerElement = headers.next();
                        if (headerElement.getElementQName().equals(soapElement.getElementQName())) {
                            headerElement.setMustUnderstand(false);
                            headerElement.setActor(null);
                        }
                    }
                }
            }
        }
    }

    protected Document parseWsrfEndpointReference(String wsrfEndpointReference) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder = factory.newDocumentBuilder();
        return builder.parse(new InputSource(new StringReader(wsrfEndpointReference)));
    }

    @Override
    public Map<String, Object> invoke(SOAPMessage message) throws Exception {
        return super.invoke(message);
    }

    public Map<String, Object> invoke(Map<String, Object> inputMap, JsonNode configurationBean) throws Exception {

        //      String securityProfile = bean.getSecurityProfile();
        //      EngineConfiguration wssEngineConfiguration = null;
        //      if (securityProfile != null) {
        //         // If security settings require WS-Security and not just e.g. Basic HTTP
        //         // AuthN - configure the axis engine from the appropriate config strings
        //         if (securityProfile
        //               .equals(SecurityProfiles.WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD)) {
        //            wssEngineConfiguration = new XMLStringProvider(
        //                  SecurityProfiles.WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD_CONFIG);
        //         } else if (securityProfile
        //               .equals(SecurityProfiles.WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD)) {
        //            wssEngineConfiguration = new XMLStringProvider(
        //                  SecurityProfiles.WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD_CONFIG);
        //         } else if (securityProfile
        //               .equals(SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_PLAINTEXTPASSWORD)) {
        //            wssEngineConfiguration = new XMLStringProvider(
        //                  SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_PLAINTETPASSWORD_CONFIG);
        //         } else if (securityProfile
        //               .equals(SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD)) {
        //            wssEngineConfiguration = new XMLStringProvider(
        //                  SecurityProfiles.WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD_CONFIG);
        //         }
        //      }
        //
        //      // This does not work
        ////      ClassUtils.setClassLoader("net.sf.taverna.t2.activities.wsdl.security.TavernaAxisCustomSSLSocketFactory",TavernaAxisCustomSSLSocketFactory.class.getClassLoader());
        //      
        //      // Setting Axis property only works when we also set the Thread's classloader as below 
        //      // (we do it from the net.sf.taverna.t2.workflowmodel.processor.dispatch.layers.Invoke.requestRun())
        ////      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        //      if (AxisProperties.getProperty("axis.socketSecureFactory")== null || !AxisProperties.getProperty("axis.socketSecureFactory").equals("net.sf.taverna.t2.activities.wsdl.security.TavernaAxisCustomSSLSocketFactory")){
        //         AxisProperties.setProperty("axis.socketSecureFactory", "net.sf.taverna.t2.activities.wsdl.security.TavernaAxisCustomSSLSocketFactory");
        //         logger.info("Setting axis.socketSecureFactory property to " + AxisProperties.getProperty("axis.socketSecureFactory"));
        //      }
        //        
        //      // This also does not work
        //      //AxisProperties.setClassDefault(SecureSocketFactory.class, "net.sf.taverna.t2.activities.wsdl.security.TavernaAxisCustomSSLSocketFactory");
        //        
        //      //Call call = super.getCall(wssEngineConfiguration);
        //      
        //      // Now that we have an axis Call object, configure any additional
        //      // security properties on it (or its message context or its Transport
        //      // handler),
        //      // such as WS-Security UsernameToken or HTTP Basic AuthN
        //      if (securityProfile != null) {
        //         configureSecurity(call, bean);
        //      }

        return invoke(inputMap);
    }

}