/*******************************************************************************
 * Copyright (c) 2004, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 * IBM Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20070305   117034 makandre@ca.ibm.com - Andrew Mak, Web Services Explorer should support SOAP Headers
 *******************************************************************************/
package org.eclipse.wst.ws.internal.explorer.platform.wsdl.actions;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.servlet.http.HttpServletResponse;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Part;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.axis.Constants;
import org.eclipse.wst.ws.internal.explorer.platform.perspective.Controller;
import org.eclipse.wst.ws.internal.explorer.platform.perspective.MessageQueue;
import org.eclipse.wst.ws.internal.explorer.platform.util.MultipartFormDataException;
import org.eclipse.wst.ws.internal.explorer.platform.util.MultipartFormDataParser;
import org.eclipse.wst.ws.internal.explorer.platform.util.XMLUtils;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.constants.WSDLActionInputs;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.Endpoint;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.WSDLBindingElement;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.WSDLElement;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.WSDLOperationElement;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.WSDLServiceElement;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.fragment.IXSDFragment;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.perspective.InvokeWSDLOperationTool;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.perspective.SOAPMessageQueue;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.perspective.WSDLPerspective;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.transport.HTTPException;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.transport.HTTPTransport;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.util.SoapHelper;
import org.eclipse.wst.ws.internal.parser.discovery.NetUtils;
import org.eclipse.wst.wsdl.binding.soap.SOAPHeader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public abstract class InvokeWSDLSOAPOperationAction extends WSDLPropertiesFormAction
{
  public InvokeWSDLSOAPOperationAction(Controller controller)
  {
    super(controller);
  }

  protected boolean processParsedResults(MultipartFormDataParser parser) throws MultipartFormDataException
  {
    super.processParsedResults(parser);
    String endPoint = parser.getParameter(WSDLActionInputs.END_POINT);
    InvokeWSDLOperationTool invokeWSDLOperationTool = (InvokeWSDLOperationTool)(getSelectedNavigatorNode().getCurrentToolManager().getSelectedTool());
    invokeWSDLOperationTool.setEndPoint(endPoint);
    return true;
  }

  protected final void addRPCWrapper(Vector bodyEntries,WSDLElement wsdlElement,WSDLOperationElement operElement,Hashtable soapEnvelopeNamespaceTable) throws ParserConfigurationException
  {
    // Must be RPC style.
    String encodingNamespaceURI = null;
    /*
     * WS-I: In a rpc-literal SOAP binding, the serialized child element of the 
     * soap:Body element consists of a wrapper element, whose namespace is the value 
     * of the namespace attribute of the soapbind:body element and whose local name is 
     * either the name of the operation or the name of the operation suffixed 
     * with "Response". The namespace attribute is required, as opposed to being 
     * optional, to ensure that the children of the soap:Body element are namespace-
     * qualified.
     */
    BindingOperation bindingOperation = operElement.getBindingOperation();
    if (bindingOperation != null)
    {
      BindingInput bindingInput = bindingOperation.getBindingInput();
      if (bindingInput != null)
      {
        List extElements = bindingInput.getExtensibilityElements();
        for (Iterator it = extElements.iterator(); it.hasNext();)
        {
          ExtensibilityElement extElement = (ExtensibilityElement)it.next();
          if (extElement instanceof SOAPBody)
          {
            encodingNamespaceURI = ((SOAPBody)extElement).getNamespaceURI();
            break;
          }
        }
      }
    }
    // If the namespace of the soapbind:body element is not set, get it from the operation element
    if (encodingNamespaceURI == null)
      encodingNamespaceURI = operElement.getEncodingNamespace();
    // If the namespace of the operation element is not set, get it from the definition element
    if (encodingNamespaceURI == null)
    {
      Definition definition = wsdlElement.getDefinition();
      encodingNamespaceURI = definition.getTargetNamespace();
    }
    // Generate an RPC style wrapper element.
    Document doc = XMLUtils.createNewDocument(null);
    String encodingStyle = (operElement.isUseLiteral() ? null : operElement.getEncodingStyle());
    Element wrapperElement = SoapHelper.createRPCWrapperElement(doc,soapEnvelopeNamespaceTable,encodingNamespaceURI,operElement.getOperation().getName(),encodingStyle);
    for (int i=0;i<bodyEntries.size();i++)
      wrapperElement.appendChild(doc.importNode((Element)bodyEntries.elementAt(i),true));
    bodyEntries.removeAllElements();
    bodyEntries.addElement(wrapperElement);
  }

  /**
   * Generate a Vector of the elements inside the Soap Header.
   * @param soapEnvelopeNamespaceTable - Hashtable containing a map of the namespace URIs to prefixes.
   * @param operElement - WSDLOperationElement encapsulating the WSDL operation.
   */
  protected Vector getHeaderEntries(Hashtable soapEnvelopeNamespaceTable,WSDLOperationElement operElement) throws ParserConfigurationException,Exception
  {
    Vector headerEntries = new Vector();
    
    Iterator it = operElement.getSOAPHeaders().iterator();
    while (it.hasNext())
    {
      SOAPHeader soapHeader = (SOAPHeader) it.next();
      
      StringBuffer encodingStyle = null;
      boolean isUseLiteral = "literal".equals(soapHeader.getUse());      
      
      if (!isUseLiteral) {
	      Iterator encodingStyles = soapHeader.getEncodingStyles().iterator();
	      encodingStyle = new StringBuffer();
	      while (encodingStyles.hasNext()) {
	    	  Object next = encodingStyles.next();
	    	  if (Constants.URI_SOAP11_ENC.equals(next))
	    		  continue;
	    	  encodingStyle.append(" ").append(next);
	      }	              
      }
      
      IXSDFragment frag = (IXSDFragment)operElement.getHeaderFragment(soapHeader);
      Element[] instanceDocuments = frag.genInstanceDocumentsFromParameterValues(!isUseLiteral,soapEnvelopeNamespaceTable, XMLUtils.createNewDocument(null));
      for (int j=0;j<instanceDocuments.length;j++)
      {
        if (instanceDocuments[j] == null)
          continue;
        if (encodingStyle != null && encodingStyle.length() > 0)
          instanceDocuments[j].setAttribute("soapenv:encodingStyle",encodingStyle.substring(1));
        headerEntries.addElement(instanceDocuments[j]);
      }
    }
	
    return headerEntries;
  }
  
  /**
   * Generate a Vector of the elements inside the Soap Body.
   * @param soapEnvelopeNamespaceTable - Hashtable containing a map of the namespace URIs to prefixes.
   * @param operElement - WSDLOperationElement encapsulating the WSDL operation.
   */
  protected Vector getBodyEntries(Hashtable soapEnvelopeNamespaceTable,WSDLOperationElement operElement,WSDLBindingElement bindingElement,WSDLServiceElement serviceElement) throws ParserConfigurationException,Exception
  {
    Vector bodyEntries = new Vector();
    boolean isUseLiteral = operElement.isUseLiteral();
    String encodingStyle = operElement.getEncodingStyle();
    boolean addEncodingStyle = (!isUseLiteral && !Constants.URI_SOAP11_ENC.equals(encodingStyle));
    Iterator it = operElement.getOrderedBodyParts().iterator();
    while (it.hasNext())
    {
      Part part = (Part)it.next();
      IXSDFragment frag = (IXSDFragment)operElement.getFragment(part);
      Element[] instanceDocuments = frag.genInstanceDocumentsFromParameterValues(!isUseLiteral,soapEnvelopeNamespaceTable, XMLUtils.createNewDocument(null));
      for (int j=0;j<instanceDocuments.length;j++)
      {
        if (instanceDocuments[j] == null)
          continue;
        if (addEncodingStyle)
          instanceDocuments[j].setAttribute("soapenv:encodingStyle",encodingStyle);
        bodyEntries.addElement(instanceDocuments[j]);
      }
    }

    if (!operElement.isDocumentStyle())
    {
      try
      {
        addRPCWrapper(bodyEntries,(WSDLElement)serviceElement.getParentElement(),operElement,soapEnvelopeNamespaceTable);
      }
      catch (ParserConfigurationException e)
      {
        throw e;
      }
    }
    return bodyEntries;
  }

  protected Element getSOAPEnvelope(Hashtable soapEnvelopeNamespaceTable, Vector bodyEntries) throws ParserConfigurationException
  {
	return getSOAPEnvelope(soapEnvelopeNamespaceTable, null, bodyEntries);
  }
  
  protected Element getSOAPEnvelope(Hashtable soapEnvelopeNamespaceTable, Vector headerEntries, Vector bodyEntries) throws ParserConfigurationException
  {
    DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = XMLUtils.createNewDocument(docBuilder);
    Element soapEnvelopeElement = SoapHelper.createSoapEnvelopeElement(doc,soapEnvelopeNamespaceTable);
    
    if (headerEntries != null && !headerEntries.isEmpty()) {
    	Element soapHeaderElement = SoapHelper.createSoapHeaderElement(doc);
        for (int i=0;i<headerEntries.size();i++)
          soapHeaderElement.appendChild(doc.importNode((Element)headerEntries.elementAt(i),true));
        soapEnvelopeElement.appendChild(soapHeaderElement);        
    }
    
    Element soapBodyElement = SoapHelper.createSoapBodyElement(doc);
    for (int i=0;i<bodyEntries.size();i++)
      soapBodyElement.appendChild(doc.importNode((Element)bodyEntries.elementAt(i),true));
    soapEnvelopeElement.appendChild(soapBodyElement);
    return soapEnvelopeElement;
  }

  private final void recordSoapRequest(SOAPMessageQueue soapRequestQueue,Hashtable soapEnvelopeNamespaceTable,Element soapEnvelope) throws ParserConfigurationException,IOException
  {
    soapRequestQueue.clear();
    soapRequestQueue.addMessage(XMLUtils.serialize(soapEnvelope,false));
  }

  private final void recordSOAPResponse(SOAPMessageQueue soapResponseQueue,BufferedReader responseReader) throws IOException
  {
    soapResponseQueue.clear();
    if (responseReader != null)
    {
      String line = null;
      while ((line = responseReader.readLine()) != null)
        soapResponseQueue.addMessage(line);
      responseReader.close();
    }
  }

  public boolean run()
  {
    String soapAddressLocation = (String)propertyTable_.get(WSDLActionInputs.END_POINT);
    WSDLPerspective wsdlPerspective = controller_.getWSDLPerspective();
    MessageQueue messageQueue = wsdlPerspective.getMessageQueue();
    WSDLOperationElement operElement = (WSDLOperationElement)getSelectedNavigatorNode().getTreeElement();
    WSDLBindingElement bindingElement = (WSDLBindingElement)operElement.getParentElement();
    WSDLServiceElement serviceElement = (WSDLServiceElement)bindingElement.getParentElement();
    operElement.setPropertyAsObject(WSDLActionInputs.SOAP_RESPONSE_CACHED, new Boolean(false));
    try
    {
      // Generate the SOAP envelope and its children. We need to create a DOM element version to display and the object version to execute.
      // <SOAP-ENV:Envelope
      //    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      //    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      //    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      // ...
      Hashtable soapEnvelopeNamespaceTable = new Hashtable();
      SoapHelper.addDefaultSoapEnvelopeNamespaces(soapEnvelopeNamespaceTable);
      Vector headerEntries = getHeaderEntries(soapEnvelopeNamespaceTable, operElement);
      Vector bodyEntries = getBodyEntries(soapEnvelopeNamespaceTable,operElement,bindingElement,serviceElement);
      Element soapEnvelope = getSOAPEnvelope(soapEnvelopeNamespaceTable, headerEntries, bodyEntries);
      recordSoapRequest(wsdlPerspective.getSOAPRequestQueue(),soapEnvelopeNamespaceTable,soapEnvelope);

      // Execute the SOAP operation.
      if (soapAddressLocation != null)
      {
        // Send the message and record the SOAP Response Envelope.
        HTTPTransport transport = createTransport(bindingElement, soapAddressLocation);
        transport.send(NetUtils.createURL(soapAddressLocation),operElement.getSoapAction(),XMLUtils.serialize(soapEnvelope, true));
        recordSOAPResponse(wsdlPerspective.getSOAPResponseQueue(),transport.receive());
        wsdlPerspective.setOperationNode(getSelectedNavigatorNode());
        return true;
      }
      throw new IOException(wsdlPerspective.getMessage("MSG_ERROR_UNABLE_TO_CONNECT",soapAddressLocation));
    }
    catch (ParserConfigurationException e)
    {
      handleUnexpectedException(wsdlPerspective,messageQueue,"ParserConfigurationException",e);
    }
    catch (IOException e)
    {
      handleUnexpectedException(wsdlPerspective,messageQueue,"IOException",e);
    }
    catch (HTTPException httpe)
    {
      throwHTTPException(bindingElement, soapAddressLocation, httpe);
    }
    catch (Exception e)
    {
      handleUnexpectedException(wsdlPerspective,messageQueue,"Exception",e);
    }
    return false;
  }
  
  private void throwHTTPException(WSDLBindingElement bindingElement, String endpointString, HTTPException httpException) throws HTTPException
  {
    if (httpException.getStatusCode() == HttpServletResponse.SC_UNAUTHORIZED)
    {
      Endpoint endpoint = bindingElement.getEndpoint(endpointString);
      if (endpoint != null)
      {
        endpoint.setRequireHTTPBasicAuth(true);
        endpoint.setHttpBasicAuthUsername(null);
        endpoint.setHttpBasicAuthPassword(null);
      }
    }
    throw httpException;
  }
  
  private HTTPTransport createTransport(WSDLBindingElement bindingElement, String endpointString)
  {
    HTTPTransport transport = new HTTPTransport();
    Endpoint endpoint = bindingElement.getEndpoint(endpointString);
    if (endpoint != null)
    {
      if (endpoint.isRequireHTTPBasicAuth())
      {
        String httpBasicAuthUsername = endpoint.getHttpBasicAuthUsername();
        String httpBasicAuthPassword = endpoint.getHttpBasicAuthPassword();
        if (httpBasicAuthUsername == null || httpBasicAuthPassword == null)
        {
          httpBasicAuthUsername = (String)propertyTable_.get(WSDLActionInputs.HTTP_BASIC_AUTH_USERNAME);
          httpBasicAuthPassword = (String)propertyTable_.get(WSDLActionInputs.HTTP_BASIC_AUTH_PASSWORD);
          endpoint.setHttpBasicAuthUsername(httpBasicAuthUsername);
          endpoint.setHttpBasicAuthPassword(httpBasicAuthPassword);
        }
        if (httpBasicAuthUsername != null && httpBasicAuthPassword != null)
        {
          transport.setHttpBasicAuthUsername(httpBasicAuthUsername);
          transport.setHttpBasicAuthPassword(httpBasicAuthPassword);
        }
      }
    }
    return transport;
  }
}