blob: bdca4ed432ea0a90f039bc43f1f5b7f89be742c0 [file] [log] [blame]
/*******************************************************************************
* 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 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.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 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
{
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;
}
}