Package com.eviware.soapui.impl.wsdl.support.soap

Source Code of com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder

/*
*  soapUI, copyright (C) 2004-2011 eviware.com
*
*  soapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
*  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU Lesser General Public License for more details at gnu.org.
*/

package com.eviware.soapui.impl.wsdl.support.soap;

import java.io.StringWriter;
import java.util.List;
import java.util.Map;

import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Message;
import javax.wsdl.Part;
import javax.xml.namespace.QName;

import org.apache.log4j.Logger;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.support.Constants;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
import com.eviware.soapui.impl.wsdl.support.xsd.SampleXmlUtil;
import com.eviware.soapui.model.iface.Interface;
import com.eviware.soapui.model.iface.MessageBuilder;
import com.eviware.soapui.model.iface.MessagePart.FaultPart;
import com.eviware.soapui.settings.WsdlSettings;
import com.eviware.soapui.support.xml.XmlUtils;

/**
* Builds SOAP requests according to WSDL/XSD definitions
*
* @author Ole.Matzura
*/

public class SoapMessageBuilder implements MessageBuilder
{
  private final static Logger log = Logger.getLogger( SoapMessageBuilder.class );

  private WsdlContext wsdlContext;
  private WsdlInterface iface;
  private Map<QName, String[]> multiValues = null;

  public SoapMessageBuilder( WsdlInterface iface ) throws Exception
  {
    this.iface = iface;
    this.wsdlContext = iface.getWsdlContext();
  }

  public SoapMessageBuilder( WsdlContext wsdlContext )
  {
    this.wsdlContext = wsdlContext;
  }

  public void setMultiValues( Map<QName, String[]> multiValues )
  {
    this.multiValues = multiValues;
  }

  public Interface getInterface()
  {
    return iface;
  }

  public String buildFault( String faultcode, String faultstring )
  {
    return buildFault( faultcode, faultstring, getSoapVersion() );
  }

  public SoapVersion getSoapVersion()
  {
    return iface == null ? wsdlContext.getSoapVersion() : iface.getSoapVersion();
  }

  public static String buildFault( String faultcode, String faultstring, SoapVersion soapVersion )
  {
    SampleXmlUtil generator = new SampleXmlUtil( false );
    generator.setTypeComment( false );
    generator.setIgnoreOptional( true );

    String emptyResponse = buildEmptyFault( generator, soapVersion );

    if( soapVersion == SoapVersion.Soap11 )
    {
      emptyResponse = XmlUtils.setXPathContent( emptyResponse, "//faultcode", faultcode );
      emptyResponse = XmlUtils.setXPathContent( emptyResponse, "//faultstring", faultstring );
    }
    else if( soapVersion == SoapVersion.Soap12 )
    {
      emptyResponse = XmlUtils.setXPathContent( emptyResponse, "//soap:Value", faultcode );
      emptyResponse = XmlUtils.setXPathContent( emptyResponse, "//soap:Text", faultstring );
      emptyResponse = XmlUtils.setXPathContent( emptyResponse, "//soap:Text/@xml:lang", "en" );
    }

    return emptyResponse;
  }

  public String buildEmptyFault()
  {
    return buildEmptyFault( getSoapVersion() );
  }

  public static String buildEmptyFault( SoapVersion soapVersion )
  {
    SampleXmlUtil generator = new SampleXmlUtil( false );

    String emptyResponse = buildEmptyFault( generator, soapVersion );

    return emptyResponse;
  }

  private static String buildEmptyFault( SampleXmlUtil generator, SoapVersion soapVersion )
  {
    String emptyResponse = buildEmptyMessage( soapVersion );
    try
    {
      // XmlObject xmlObject = XmlObject.Factory.parse( emptyResponse );
      XmlObject xmlObject = XmlUtils.createXmlObject( emptyResponse );
      XmlCursor cursor = xmlObject.newCursor();

      if( cursor.toChild( soapVersion.getEnvelopeQName() ) && cursor.toChild( soapVersion.getBodyQName() ) )
      {
        SchemaType faultType = soapVersion.getFaultType();
        Node bodyNode = cursor.getDomNode();
        Document dom = XmlUtils.parseXml( generator.createSample( faultType ) );
        bodyNode.appendChild( bodyNode.getOwnerDocument().importNode( dom.getDocumentElement(), true ) );
      }

      cursor.dispose();
      emptyResponse = xmlObject.toString();
    }
    catch( Exception e )
    {
      SoapUI.logError( e );
    }
    return emptyResponse;
  }

  public String buildEmptyMessage()
  {
    return buildEmptyMessage( getSoapVersion() );
  }

  public static String buildEmptyMessage( SoapVersion soapVersion )
  {
    SampleXmlUtil generator = new SampleXmlUtil( false );
    generator.setTypeComment( false );
    generator.setIgnoreOptional( true );
    return generator.createSample( soapVersion.getEnvelopeType() );
  }

  public String buildSoapMessageFromInput( BindingOperation bindingOperation, boolean buildOptional ) throws Exception
  {
    return buildSoapMessageFromInput( bindingOperation, buildOptional, true );
  }

  public String buildSoapMessageFromInput( BindingOperation bindingOperation, boolean buildOptional,
      boolean alwaysBuildHeaders ) throws Exception
  {
    boolean inputSoapEncoded = WsdlUtils.isInputSoapEncoded( bindingOperation );
    SampleXmlUtil xmlGenerator = new SampleXmlUtil( inputSoapEncoded );
    xmlGenerator.setMultiValues( multiValues );
    xmlGenerator.setIgnoreOptional( !buildOptional );

    XmlObject object = XmlObject.Factory.newInstance();
    XmlCursor cursor = object.newCursor();
    cursor.toNextToken();
    cursor.beginElement( wsdlContext.getSoapVersion().getEnvelopeQName() );

    if( inputSoapEncoded )
    {
      cursor.insertNamespace( "xsi", Constants.XSI_NS );
      cursor.insertNamespace( "xsd", Constants.XSD_NS );
    }

    cursor.toFirstChild();

    cursor.beginElement( wsdlContext.getSoapVersion().getBodyQName() );
    cursor.toFirstChild();

    if( WsdlUtils.isRpc( wsdlContext.getDefinition(), bindingOperation ) )
    {
      buildRpcRequest( bindingOperation, cursor, xmlGenerator );
    }
    else
    {
      buildDocumentRequest( bindingOperation, cursor, xmlGenerator );
    }

    if( alwaysBuildHeaders )
    {
      BindingInput bindingInput = bindingOperation.getBindingInput();
      if( bindingInput != null )
      {
        List<?> extensibilityElements = bindingInput.getExtensibilityElements();
        List<SoapHeader> soapHeaders = WsdlUtils.getSoapHeaders( extensibilityElements );
        addHeaders( soapHeaders, cursor, xmlGenerator );
      }
    }
    cursor.dispose();

    try
    {
      StringWriter writer = new StringWriter();
      XmlUtils.serializePretty( object, writer );
      return writer.toString();
    }
    catch( Exception e )
    {
      SoapUI.logError( e );
      return object.xmlText();
    }
  }

  private void addHeaders( List<SoapHeader> headers, XmlCursor cursor, SampleXmlUtil xmlGenerator ) throws Exception
  {
    // reposition
    cursor.toStartDoc();
    cursor.toChild( wsdlContext.getSoapVersion().getEnvelopeQName() );
    cursor.toFirstChild();

    cursor.beginElement( wsdlContext.getSoapVersion().getHeaderQName() );
    cursor.toFirstChild();

    for( int i = 0; i < headers.size(); i++ )
    {
      SoapHeader header = headers.get( i );

      Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
      if( message == null )
      {
        log.error( "Missing message for header: " + header.getMessage() );
        continue;
      }

      Part part = message.getPart( header.getPart() );

      if( part != null )
        createElementForPart( part, cursor, xmlGenerator );
      else
        log.error( "Missing part for header; " + header.getPart() );
    }
  }

  public void createElementForPart( Part part, XmlCursor cursor, SampleXmlUtil xmlGenerator ) throws Exception
  {
    QName elementName = part.getElementName();
    QName typeName = part.getTypeName();

    if( elementName != null )
    {
      cursor.beginElement( elementName );

      if( wsdlContext.hasSchemaTypes() )
      {
        SchemaGlobalElement elm = wsdlContext.getSchemaTypeLoader().findElement( elementName );
        if( elm != null )
        {
          cursor.toFirstChild();
          xmlGenerator.createSampleForType( elm.getType(), cursor );
        }
        else
          log.error( "Could not find element [" + elementName + "] specified in part [" + part.getName() + "]" );
      }

      cursor.toParent();
    }
    else
    {
      // cursor.beginElement( new QName(
      // wsdlContext.getWsdlDefinition().getTargetNamespace(), part.getName()
      // ));
      cursor.beginElement( part.getName() );
      if( typeName != null && wsdlContext.hasSchemaTypes() )
      {
        SchemaType type = wsdlContext.getSchemaTypeLoader().findType( typeName );

        if( type != null )
        {
          cursor.toFirstChild();
          xmlGenerator.createSampleForType( type, cursor );
        }
        else
          log.error( "Could not find type [" + typeName + "] specified in part [" + part.getName() + "]" );
      }

      cursor.toParent();
    }
  }

  private void buildDocumentRequest( BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator )
      throws Exception
  {
    Part[] parts = WsdlUtils.getInputParts( bindingOperation );

    for( int i = 0; i < parts.length; i++ )
    {
      Part part = parts[i];
      if( !WsdlUtils.isAttachmentInputPart( part, bindingOperation )
          && ( part.getElementName() != null || part.getTypeName() != null ) )
      {
        XmlCursor c = cursor.newCursor();
        c.toLastChild();
        createElementForPart( part, c, xmlGenerator );
        c.dispose();
      }
    }
  }

  private void buildDocumentResponse( BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator )
      throws Exception
  {
    Part[] parts = WsdlUtils.getOutputParts( bindingOperation );

    for( int i = 0; i < parts.length; i++ )
    {
      Part part = parts[i];

      if( !WsdlUtils.isAttachmentOutputPart( part, bindingOperation )
          && ( part.getElementName() != null || part.getTypeName() != null ) )
      {
        XmlCursor c = cursor.newCursor();
        c.toLastChild();
        createElementForPart( part, c, xmlGenerator );
        c.dispose();
      }
    }
  }

  private void buildRpcRequest( BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator )
      throws Exception
  {
    // rpc requests use the operation name as root element
    String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingInput().getExtensibilityElements() );
    if( ns == null )
    {
      ns = WsdlUtils.getTargetNamespace( wsdlContext.getDefinition() );
      log.warn( "missing namespace on soapbind:body for RPC request, using targetNamespace instead (BP violation)" );
    }

    cursor.beginElement( new QName( ns, bindingOperation.getName() ) );
    if( xmlGenerator.isSoapEnc() )
      cursor.insertAttributeWithValue( new QName( wsdlContext.getSoapVersion().getEnvelopeNamespace(),
          "encodingStyle" ), wsdlContext.getSoapVersion().getEncodingNamespace() );

    Part[] inputParts = WsdlUtils.getInputParts( bindingOperation );
    for( int i = 0; i < inputParts.length; i++ )
    {
      Part part = inputParts[i];
      if( WsdlUtils.isAttachmentInputPart( part, bindingOperation ) )
      {
        if( iface.getSettings().getBoolean( WsdlSettings.ATTACHMENT_PARTS ) )
        {
          XmlCursor c = cursor.newCursor();
          c.toLastChild();
          c.beginElement( part.getName() );
          c.insertAttributeWithValue( "href", part.getName() + "Attachment" );
          c.dispose();
        }
      }
      else
      {
        if( wsdlContext.hasSchemaTypes() )
        {
          QName typeName = part.getTypeName();
          if( typeName != null )
          {
            SchemaType type = wsdlContext.getInterfaceDefinition().findType( typeName );

            if( type != null )
            {
              XmlCursor c = cursor.newCursor();
              c.toLastChild();
              c.insertElement( part.getName() );
              c.toPrevToken();

              xmlGenerator.createSampleForType( type, c );
              c.dispose();
            }
            else
              log.warn( "Failed to find type [" + typeName + "]" );
          }
          else
          {
            SchemaGlobalElement element = wsdlContext.getSchemaTypeLoader().findElement( part.getElementName() );
            if( element != null )
            {
              XmlCursor c = cursor.newCursor();
              c.toLastChild();
              c.insertElement( element.getName() );
              c.toPrevToken();

              xmlGenerator.createSampleForType( element.getType(), c );
              c.dispose();
            }
            else
              log.warn( "Failed to find element [" + part.getElementName() + "]" );
          }
        }
      }
    }
  }

  private void buildRpcResponse( BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator )
      throws Exception
  {
    // rpc requests use the operation name as root element
    BindingOutput bindingOutput = bindingOperation.getBindingOutput();
    String ns = bindingOutput == null ? null : WsdlUtils.getSoapBodyNamespace( bindingOutput
        .getExtensibilityElements() );

    if( ns == null )
    {
      ns = WsdlUtils.getTargetNamespace( wsdlContext.getDefinition() );
      log.warn( "missing namespace on soapbind:body for RPC response, using targetNamespace instead (BP violation)" );
    }

    cursor.beginElement( new QName( ns, bindingOperation.getName() + "Response" ) );
    if( xmlGenerator.isSoapEnc() )
      cursor.insertAttributeWithValue( new QName( wsdlContext.getSoapVersion().getEnvelopeNamespace(),
          "encodingStyle" ), wsdlContext.getSoapVersion().getEncodingNamespace() );

    Part[] inputParts = WsdlUtils.getOutputParts( bindingOperation );
    for( int i = 0; i < inputParts.length; i++ )
    {
      Part part = inputParts[i];
      if( WsdlUtils.isAttachmentOutputPart( part, bindingOperation ) )
      {
        if( iface.getSettings().getBoolean( WsdlSettings.ATTACHMENT_PARTS ) )
        {
          XmlCursor c = cursor.newCursor();
          c.toLastChild();
          c.beginElement( part.getName() );
          c.insertAttributeWithValue( "href", part.getName() + "Attachment" );
          c.dispose();
        }
      }
      else
      {
        if( wsdlContext.hasSchemaTypes() )
        {
          QName typeName = part.getTypeName();
          if( typeName != null )
          {
            SchemaType type = wsdlContext.getInterfaceDefinition().findType( typeName );

            if( type != null )
            {
              XmlCursor c = cursor.newCursor();
              c.toLastChild();
              c.insertElement( part.getName() );
              c.toPrevToken();

              xmlGenerator.createSampleForType( type, c );
              c.dispose();
            }
            else
              log.warn( "Failed to find type [" + typeName + "]" );
          }
          else
          {
            SchemaGlobalElement element = wsdlContext.getSchemaTypeLoader().findElement( part.getElementName() );
            if( element != null )
            {
              XmlCursor c = cursor.newCursor();
              c.toLastChild();
              c.insertElement( element.getName() );
              c.toPrevToken();

              xmlGenerator.createSampleForType( element.getType(), c );
              c.dispose();
            }
            else
              log.warn( "Failed to find element [" + part.getElementName() + "]" );
          }
        }
      }
    }
  }

  public void setWsdlContext( WsdlContext wsdlContext )
  {
    this.wsdlContext = wsdlContext;
  }

  public void setInterface( WsdlInterface iface )
  {
    this.iface = iface;
  }

  public String buildSoapMessageFromOutput( BindingOperation bindingOperation, boolean buildOptional )
      throws Exception
  {
    return buildSoapMessageFromOutput( bindingOperation, buildOptional, true );
  }

  public String buildSoapMessageFromOutput( BindingOperation bindingOperation, boolean buildOptional,
      boolean alwaysBuildHeaders ) throws Exception
  {
    boolean inputSoapEncoded = WsdlUtils.isInputSoapEncoded( bindingOperation );
    SampleXmlUtil xmlGenerator = new SampleXmlUtil( inputSoapEncoded );
    xmlGenerator.setIgnoreOptional( !buildOptional );
    xmlGenerator.setMultiValues( multiValues );

    XmlObject object = XmlObject.Factory.newInstance();
    XmlCursor cursor = object.newCursor();
    cursor.toNextToken();
    cursor.beginElement( wsdlContext.getSoapVersion().getEnvelopeQName() );

    if( inputSoapEncoded )
    {
      cursor.insertNamespace( "xsi", Constants.XSI_NS );
      cursor.insertNamespace( "xsd", Constants.XSD_NS );
    }

    cursor.toFirstChild();

    cursor.beginElement( wsdlContext.getSoapVersion().getBodyQName() );
    cursor.toFirstChild();

    if( WsdlUtils.isRpc( wsdlContext.getDefinition(), bindingOperation ) )
    {
      buildRpcResponse( bindingOperation, cursor, xmlGenerator );
    }
    else
    {
      buildDocumentResponse( bindingOperation, cursor, xmlGenerator );
    }

    if( alwaysBuildHeaders )
    {
      // bindingOutput will be null for one way operations,
      // but then we shouldn't be here in the first place???
      BindingOutput bindingOutput = bindingOperation.getBindingOutput();
      if( bindingOutput != null )
      {
        List<?> extensibilityElements = bindingOutput.getExtensibilityElements();
        List<SoapHeader> soapHeaders = WsdlUtils.getSoapHeaders( extensibilityElements );
        addHeaders( soapHeaders, cursor, xmlGenerator );
      }
    }
    cursor.dispose();

    try
    {
      StringWriter writer = new StringWriter();
      XmlUtils.serializePretty( object, writer );
      return writer.toString();
    }
    catch( Exception e )
    {
      SoapUI.logError( e );
      return object.xmlText();
    }
  }

  public String buildFault( FaultPart faultPart )
  {
    SampleXmlUtil generator = new SampleXmlUtil( false );
    generator.setExampleContent( false );
    generator.setTypeComment( false );
    generator.setMultiValues( multiValues );
    String faultResponse = iface.getMessageBuilder().buildEmptyFault();

    XmlCursor cursor = null;
    try
    {
      // XmlObject xmlObject = XmlObject.Factory.parse( faultResponse );
      XmlObject xmlObject = XmlUtils.createXmlObject( faultResponse );
      XmlObject[] detail = xmlObject.selectPath( "//detail" );
      if( detail.length > 0 )
      {
        cursor = detail[0].newCursor();

        cursor.toFirstContentToken();

        generator.setTypeComment( true );
        generator.setIgnoreOptional( iface.getSettings().getBoolean(
            WsdlSettings.XML_GENERATION_ALWAYS_INCLUDE_OPTIONAL_ELEMENTS ) );

        for( Part part : faultPart.getWsdlParts() )
          createElementForPart( part, cursor, generator );
      }

      faultResponse = xmlObject.xmlText( new XmlOptions().setSaveAggressiveNamespaces().setSavePrettyPrint() );
    }
    catch( Exception e1 )
    {
      SoapUI.logError( e1 );
    }
    finally
    {
      if( cursor != null )
        cursor.dispose();
    }

    return faultResponse;
  }
}
TOP

Related Classes of com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.