All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.novartis.opensource.yada.adaptor.SOAPAdaptor Maven / Gradle / Ivy

/**
 * Copyright 2016 Novartis Institutes for BioMedical Research Inc.
 * Licensed 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 com.novartis.opensource.yada.adaptor;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.novartis.opensource.yada.ConnectionFactory;
import com.novartis.opensource.yada.Finder;
import com.novartis.opensource.yada.YADAConnectionException;
import com.novartis.opensource.yada.YADAQuery;
import com.novartis.opensource.yada.YADAQueryResult;
import com.novartis.opensource.yada.YADARequest;
import com.novartis.opensource.yada.YADAResourceException;

/**
 * For execution of SOAP requests
 * @author David Varon
 *
 */
public class SOAPAdaptor extends Adaptor {

	/**
	 * Local logger handle
	 */
	private static Logger l = Logger.getLogger(SOAPAdaptor.class);
	/**
	 * Constant equal to {@value}
	 */
	private static final String AUTH_BASIC          = "Basic";
	/**
	 * Constant equal to {@value}
	 */
	private static final String AUTH_NTLM           = "ntlm";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_USER_KEY 		  = "SOAPUser";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_PASSWORD_KEY 	= "SOAPPassword";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_AUTH_KEY 		  = "SOAPAuth";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_ACTION_KEY 	  = "SOAPAction";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_DATA_KEY 		  = "SOAPData";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_DOMAIN_KEY   	= "SOAPDomain";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String SOAP_PATH_KEY		    = "SOAPPath";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String YADA_BIN            = "yada_bin";
	/**
	 * Constant equal to: {@value}
	 */
	public  static final String PROTOCOL_SOAP       = "soap";
	/**
	 * Constant equal to: {@value}
	 */
	public  static final String PROTOCOL_HTTP       = "http";
	/**
	 * Constant equal to: {@value}
	 */
	private static final String CURL_EXEC           = "/curlerWS.sh";
	//private static final String NTLM_ADAPTOR		= Finder.getEnv("yada_bin")+"curlerWS.sh";
	/**
	 * Soap endpoint username
	 */
	private String soapUser     = "";
	/**
	 * Soap endpoint password
	 */
	private String soapPass     = "";
	/**
	 * Soap endpoint domain
	 */
	private String soapDomain   = "NANET";
	/**
	 * Soap endpoint authorization type, defaults to {@link #AUTH_BASIC}
	 */
	private String soapAuth     = AUTH_BASIC;
	/**
	 * Instance variable for soap action, derived from query spec
	 */
	private String soapAction   = "";
	/**
	 * Instance variable for soap data, derived from query spec
	 */
	private String soapData     = "";
	/**
	 * Instance variable for soap path, derived from query spec
	 */
	private String soapPath		= "";
	/**
	 * Instance variable for soap endpoint, derived from query spec
	 */
	private URL    endpoint;
	/**
	 * Instance variable for soap source, derived from query spec
	 */
	private String soapSource;
	/**
	 * Instance variable for soap querystring, derived from query spec
	 */
	private String queryString;
	
	/**
	 * Inner class for facilation of SOAP authentication 
	 * @author David Varon
	 * @see java.net.Authenticator
	 */
	class YadaSoapAuthenticator extends Authenticator {
		/**
		 * Instance variable for username
		 */
		String user;
		/**
		 * Instance variable for password
		 */
		String pass;
		/**
		 * Instance variable for domain
		 */
		String domain = null;
		
		/**
		 * Constructor with domain
		 * @param user username to authenticate
		 * @param pass password to use for authentication
		 * @param domain NTML domain for user
		 */
		public YadaSoapAuthenticator(String user, String pass, String domain)
		{
			this.user = user;
			this.pass = pass;
			this.domain = domain;
		}
		
		/**
		 * Constructor without domain
		 * @param user username to authenticate
		 * @param pass password to use for authentication
		 */
		public YadaSoapAuthenticator(String user, String pass)
		{
			
			this.user = user;
			this.pass = pass;
		}
		
		@Override
		public PasswordAuthentication getPasswordAuthentication() {
        // I haven't checked getRequestingScheme() here, since for NTLM
        // and Negotiate, the usrname and password are all the same.
        System.err.println("Feeding username and password for " + getRequestingScheme());
        if (null == this.domain)
        {
        	return (new PasswordAuthentication(this.user, this.pass.toCharArray()));
        }
       	return (new PasswordAuthentication(this.domain+"\\"+this.user, this.pass.toCharArray()));
    }
	}
	
	/**
	 * Default constructor
	 */
	public SOAPAdaptor() {
		super();
		l.debug("Initializing");
	}
	
	/**
	 * Preferred "YADARequest" constructor
	 * @param yadaReq YADA request configuration
	 */
	public SOAPAdaptor(YADARequest yadaReq) {
		super(yadaReq);
	}
	
	/**
	 * Sets soap request authentication, action, connection, and request metadata.
	 * @param yq the {@link YADAQuery} containing the source code and metadata required to construct an executable query
	 * @return SOAP request source and path
	 * @throws YADAAdaptorException when the stored SOAP query specs cannot be parsed into a SOAP message
	 */
	@Override
	public String build(YADAQuery yq) throws YADAAdaptorException {
	  String conf     = ConnectionFactory.getConnectionFactory().getWsSourceMap().get(yq.getApp());
		String queryStr = yq.getYADACode();
		try {
			JSONObject querySpec = new JSONObject(queryStr);
			this.soapUser     = querySpec.getString(SOAP_USER_KEY);
			this.soapPass     = querySpec.getString(SOAP_PASSWORD_KEY);
			this.soapAction   = querySpec.getString(SOAP_ACTION_KEY);
			this.soapData     = querySpec.getString(SOAP_DATA_KEY);
			this.soapSource   = conf;
			
			if (querySpec.has(SOAP_DOMAIN_KEY))
			{
				this.soapDomain = querySpec.getString(SOAP_DOMAIN_KEY);
			}
			if (querySpec.has(SOAP_AUTH_KEY))
			{
				this.soapAuth   = querySpec.getString(SOAP_AUTH_KEY);
			}
			if (querySpec.has(SOAP_PATH_KEY))
			{
				this.soapPath   = querySpec.getString(SOAP_PATH_KEY);
			}
		} 
		catch (JSONException e) 
		{
			String msg = "Unable to process stored JSON soap specification.";
			throw new YADAAdaptorException(msg,e);
		}
		return this.soapSource+this.soapPath;
	}
	
	/**
	 * Constructs and executes a SOAP message.  For {@code basic} authentication, YADA uses the 
	 * java soap api, and the {@link SOAPConnection} object stored in the query object.  For 
	 * NTLM, which was never successful using the java api, YADA calls out to {@link #CURL_EXEC}
	 * in {@link #YADA_BIN}. 
	 * @see com.novartis.opensource.yada.adaptor.Adaptor#execute(com.novartis.opensource.yada.YADAQuery)
	 */
	@Override
	public void execute(YADAQuery yq) throws YADAAdaptorExecutionException
	{
		String result = "";
		resetCountParameter(yq);
		SOAPConnection connection = (SOAPConnection)yq.getConnection();
		for(int row=0;row args = new ArrayList<>();
					args.add(Finder.getEnv(YADA_BIN)+CURL_EXEC);
					args.add("-X");	
					args.add("-s");
					args.add(this.soapSource+this.soapPath);
					args.add("-u");
					args.add(this.soapDomain+"\\"+this.soapUser);
					args.add("-p");
					args.add(this.soapPass);
					args.add("-a");
					args.add(this.soapAuth);
					args.add("-q");
					args.add(this.soapData);
					args.add("-t");
					args.add(this.soapAction);
					String[] cmds = args.toArray(new String[0]);
					l.debug("Executing soap request via script: "+Arrays.toString(cmds));
					String s = null;
					try
					{
						ProcessBuilder pb = new ProcessBuilder(args);
						l.debug(pb.environment().toString());
						pb.redirectErrorStream(true);
						Process p = pb.start();
						try(BufferedReader si = new BufferedReader(new InputStreamReader(p.getInputStream())))
						{
  						while ((s = si.readLine()) != null)
  						{
  							l.debug(s);
  							if(null == result)
  							{
  								result = "";
  							}
  							result += s;
  						}
						}
					}
					catch(IOException e)
					{
						String msg = "Unable to execute NTLM-authenticated SOAP call using system call to 'curl'.  Make sure the curl executable is still accessible.";
						throw new YADAAdaptorExecutionException(msg,e);
					}
				}
			}
			catch (SOAPException e) 
			{
				String msg = "There was a problem creating or executing the SOAP message, or receiving the response.";
				throw new YADAAdaptorExecutionException(msg,e);
			} 
			catch (SAXException e) 
			{
				String msg = "Unable to parse SOAP message body.";
				throw new YADAAdaptorExecutionException(msg,e);
			} 
			catch (ParserConfigurationException e) 
			{
				String msg = "There was a problem creating the xml document for the SOAP message body.";
				throw new YADAAdaptorExecutionException(msg,e);
			} 
			catch (YADAResourceException e)
			{
				String msg = "Cannot find 'curl' executable at specified JNDI path "+YADA_BIN+CURL_EXEC;
				throw new YADAAdaptorExecutionException(msg,e);
			} 
			catch (MalformedURLException e)
			{
				String msg = "Can't create URL from provided source and path.";
				throw new YADAAdaptorExecutionException(msg,e);
			}
			finally
			{
				try
				{
					ConnectionFactory.releaseResources(connection,yq.getSoap().get(0));
				} 
				catch (YADAConnectionException e)
				{
					l.error(e.getMessage());
				}
			}
			
			yqr.addResult(row, result);
			
		}
		
	}
	
	
	/*
	public String getJSON() throws YADAAdaptorException, SQLException
	{
		String json = "";
		try
		{
			String soapResponse = getSOAPResponse();
			l.debug("Fixing Micro$oft's W3C spec non-compliance issue");
			soapResponse = soapResponse.replace("#RowsetSchema", "http://www.microsoft.com/RowsetSchema");
		
			JSONObject jsonResponse = new JSONObject();
			jsonResponse.put("SOAPResponse", new JSONObject());
			JSONObject jsonRs = jsonResponse.getJSONObject("SOAPResponse");
			jsonRs.put("DATA",soapResponse);
			json = jsonResponse.toString();
		}
		catch (JSONException e)
		{
			l.error(e.getMessage());
			e.printStackTrace();
			throw new YADAAdaptorException();
		} 
		catch (YADAFinderException e) 
		{
			l.error(e.getMessage());
			e.printStackTrace();
			throw new YADAAdaptorException();
		}
		return json;
	}
	
	public String getXML() throws YADAAdaptorException, SQLException 
	{
		l.debug("Getting XML in SOAPAdaptor");
		String xml = null;
		try 
		{
			xml = getSOAPResponse();
			l.debug("Fixing Micro$oft's W3C spec non-compliance issue");
			xml = xml.replace("#RowsetSchema", "http://www.microsoft.com/RowsetSchema");
		} 
		catch (YADAFinderException e) 
		{
			l.error(e.getMessage());
			e.printStackTrace();
			throw new YADAAdaptorException();
		}
		
		return xml;
	}*/
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy