/*******************************************************************************
 * Copyright (c) 2004 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
 *******************************************************************************/
package org.eclipse.wst.ws.internal.explorer.platform.wsdl.actions;

import org.eclipse.wst.ws.internal.explorer.platform.perspective.*;
import org.eclipse.wst.ws.internal.explorer.platform.util.*;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.constants.*;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.datamodel.*;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.fragment.*;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.perspective.*;
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.*;
import org.eclipse.wst.ws.internal.parser.discovery.*;

import org.apache.axis.Constants;

import org.w3c.dom.*;

import javax.xml.parsers.*;
import javax.wsdl.*;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.servlet.http.HttpServletResponse;

import java.util.*;
import java.io.*;

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 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);
      XSDToFragmentConfiguration config = frag.getXSDToFragmentConfiguration();
      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
  {
    DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = XMLUtils.createNewDocument(docBuilder);
    Element soapEnvelopeElement = SoapHelper.createSoapEnvelopeElement(doc,soapEnvelopeNamespaceTable);
    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 bodyEntries = getBodyEntries(soapEnvelopeNamespaceTable,operElement,bindingElement,serviceElement);
      Element soapEnvelope = getSOAPEnvelope(soapEnvelopeNamespaceTable, 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;
  }
}