Package com.eviware.soapui.impl.wsdl.mock

Source Code of com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner

/*
*  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.mock;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLWriter;

import org.apache.commons.collections.list.TreeList;
import org.apache.log4j.Logger;
import org.xml.sax.InputSource;

import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.WsdlInterfaceFactory;
import com.eviware.soapui.impl.support.definition.export.WsdlDefinitionExporter;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
import com.eviware.soapui.model.iface.Interface;
import com.eviware.soapui.model.mock.MockResult;
import com.eviware.soapui.model.mock.MockRunListener;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.support.AbstractMockRunner;
import com.eviware.soapui.model.support.ModelSupport;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.support.xml.XmlUtils;

/**
* MockRunner that dispatches Http Requests to their designated
* WsdlMockOperation if possible
*
* @author ole.matzura
*/

@SuppressWarnings( "unchecked" )
public class WsdlMockRunner extends AbstractMockRunner
{
  private WsdlMockService mockService;
  private final List<WsdlMockResult> mockResults = Collections.synchronizedList( new TreeList() );
  private long maxResults = 100;
  private int removed = 0;
  private final WsdlMockRunContext mockContext;
  private final Map<String, StringToStringMap> wsdlCache = new HashMap<String, StringToStringMap>();
  private boolean running;
  private boolean logEnabled = true;
  private final static Logger log = Logger.getLogger( WsdlMockRunner.class );

  public WsdlMockRunner( WsdlMockService mockService, WsdlTestRunContext context ) throws Exception
  {
    this.mockService = mockService;

    Set<WsdlInterface> interfaces = new HashSet<WsdlInterface>();

    for( int i = 0; i < mockService.getMockOperationCount(); i++ )
    {
      WsdlOperation operation = mockService.getMockOperationAt( i ).getOperation();
      if( operation != null )
        interfaces.add( operation.getInterface() );
    }

    for( WsdlInterface iface : interfaces )
      iface.getWsdlContext().loadIfNecessary();

    initWsdlCache();

    mockContext = new WsdlMockRunContext( mockService, context );

    start();
  }

  private void initWsdlCache()
  {
    for( Interface iface : mockService.getMockedInterfaces() )
    {
      if( !iface.getInterfaceType().equals( WsdlInterfaceFactory.WSDL_TYPE ) )
        continue;

      try
      {
        WsdlDefinitionExporter exporter = new WsdlDefinitionExporter( ( WsdlInterface )iface );

        String wsdlPrefix = getInterfacePrefix( iface ).substring( 1 );
        StringToStringMap parts = exporter.createFilesForExport( "/" + wsdlPrefix + "&part=" );

        for( String key : parts.keySet() )
        {
          if( key.toLowerCase().endsWith( ".wsdl" ) )
          {
            InputSource inputSource = new InputSource( new StringReader( parts.get( key ) ) );
            String content = WsdlUtils.replacePortEndpoint( ( WsdlInterface )iface, inputSource,
                mockService.getLocalMockServiceEndpoint() );

            if( content != null )
              parts.put( key, content );
          }
        }

        wsdlCache.put( iface.getName(), parts );

        log.info( "Mounted WSDL for interface [" + iface.getName() + "] at [" + getOverviewUrl() + "]" );
      }
      catch( Exception e )
      {
        SoapUI.logError( e );
      }
    }
  }

  public String getInterfacePrefix( Interface iface )
  {
    String wsdlPrefix = getOverviewUrl() + "&interface=" + iface.getName();
    return wsdlPrefix;
  }

  public WsdlMockRunContext getMockContext()
  {
    return mockContext;
  }

  public synchronized void addMockResult( WsdlMockResult mockResult )
  {
    if( maxResults > 0 && logEnabled )
      mockResults.add( mockResult );

    while( mockResults.size() > maxResults )
    {
      mockResults.remove( 0 );
      removed++ ;
    }
  }

  public boolean isRunning()
  {
    return running;
  }

  public void stop()
  {
    if( !isRunning() )
      return;

    SoapUI.getMockEngine().stopMockService( this );

    MockRunListener[] mockRunListeners = mockService.getMockRunListeners();

    for( MockRunListener listener : mockRunListeners )
    {
      listener.onMockRunnerStop( this );
    }

    try
    {
      mockService.runStopScript( mockContext, this );
      running = false;
    }
    catch( Exception e )
    {
      SoapUI.logError( e );
    }
  }

  public WsdlMockService getMockService()
  {
    return mockService;
  }

  public long getMaxResults()
  {
    return maxResults;
  }

  public synchronized void setMaxResults( long l )
  {
    this.maxResults = l;

    while( mockResults.size() > l )
    {
      mockResults.remove( 0 );
      removed++ ;
    }
  }

  @Override
  public MockResult dispatchHeadRequest( HttpServletRequest request, HttpServletResponse response )
      throws DispatchException
  {
    response.setStatus( HttpServletResponse.SC_OK );
    return null;
  }

  public WsdlMockResult dispatchPostRequest( WsdlMockRequest mockRequest ) throws Exception
  {
    WsdlMockResult result = null;

    try
    {
      long timestamp = System.currentTimeMillis();

      SoapVersion soapVersion = mockRequest.getSoapVersion();
      if( soapVersion == null )
        throw new DispatchException( "Unrecognized SOAP Version" );

      String soapAction = mockRequest.getSoapAction();
      WsdlOperation operation = null;

      if( SoapUtils.isSoapFault( mockRequest.getRequestContent(), soapVersion ) )
      {
        // we should inspect fault detail and try to find matching operation
        // but not for now..
        WsdlMockOperation faultMockOperation = mockService.getFaultMockOperation();
        if( faultMockOperation != null )
          operation = faultMockOperation.getOperation();
      }
      else
      {
        try
        {
          operation = SoapUtils.findOperationForRequest( soapVersion, soapAction,
              mockRequest.getRequestXmlObject(), mockService.getMockedOperations(),
              mockService.isRequireSoapVersion(), mockService.isRequireSoapAction(),
              mockRequest.getRequestAttachments() );
        }
        catch( Exception e )
        {
          if( mockService.isDispatchResponseMessages() )
          {
            try
            {
              operation = SoapUtils.findOperationForResponse( soapVersion, soapAction,
                  mockRequest.getRequestXmlObject(), mockService.getMockedOperations(),
                  mockService.isRequireSoapVersion(), mockService.isRequireSoapAction() );

              if( operation != null )
              {
                mockRequest.setResponseMessage( true );
              }
            }
            catch( Exception e2 )
            {
              throw e;
            }
          }
          else
          {
            throw e;
          }
        }
      }

      if( operation != null )
      {
        WsdlMockOperation mockOperation = mockService.getMockOperation( operation );
        if( mockOperation != null )
        {
          long startTime = System.nanoTime();
          // try
          // {
          result = mockOperation.dispatchRequest( mockRequest );
          // }
          // catch( DispatchException e )
          // {
          // result = new WsdlMockResult( mockRequest );
          //
          // String fault = SoapMessageBuilder.buildFault( "Server",
          // e.getMessage(), mockRequest.getSoapVersion() );
          // result.setResponseContent( fault );
          // result.setMockOperation( mockOperation );
          //
          // mockRequest.getHttpResponse().getWriter().write( fault );
          // }

          if( mockRequest.getHttpRequest() instanceof org.mortbay.jetty.Request )
            ( ( org.mortbay.jetty.Request )mockRequest.getHttpRequest() ).setHandled( true );

          result.setTimeTaken( ( System.nanoTime() - startTime ) / 1000000 );
          result.setTimestamp( timestamp );
          addMockResult( result );
          return result;
        }
        else
        {
          throw new DispatchException( "Failed to find matching operation for request" );
        }
      }

      throw new DispatchException( "Missing operation for soapAction [" + soapAction + "] and body element ["
          + XmlUtils.getQName( mockRequest.getContentElement() ) + "] with SOAP Version ["
          + mockRequest.getSoapVersion() + "]" );
    }
    catch( Exception e )
    {
      if( e instanceof DispatchException )
        throw ( DispatchException )e;

      throw new DispatchException( e );
    }
  }

  public MockResult getMockResultAt( int index )
  {
    return index <= removed ? null : mockResults.get( index - removed );
  }

  public int getMockResultCount()
  {
    return mockResults.size() + removed;
  }

  public synchronized void clearResults()
  {
    mockResults.clear();
  }

  public void release()
  {
    clearResults();
    mockService = null;
    mockContext.clear();
  }

  @Override
  public MockResult dispatchRequest( HttpServletRequest request, HttpServletResponse response )
      throws DispatchException
  {
    Object result = null;

    try
    {
      for( MockRunListener listener : mockService.getMockRunListeners() )
      {
        result = listener.onMockRequest( this, request, response );
        if( result instanceof MockResult )
          return ( MockResult )result;
      }

      WsdlMockRequest mockRequest = new WsdlMockRequest( request, response, mockContext );
      result = mockService.runOnRequestScript( mockContext, this, mockRequest );
      if( !( result instanceof MockResult ) )
      {
        String method = mockRequest.getMethod();

        if( method.equals( "POST" ) )
          result = dispatchPostRequest( mockRequest );
        else
          result = super.dispatchRequest( request, response );
      }

      mockService.runAfterRequestScript( mockContext, this, ( MockResult )result );
      return ( MockResult )result;
    }
    catch( Throwable e )
    {
      if( e instanceof DispatchException )
        throw ( DispatchException )e;
      else
        throw new DispatchException( e );
    }
    finally
    {
      if( result instanceof MockResult )
      {
        for( MockRunListener listener : mockService.getMockRunListeners() )
        {
          listener.onMockResult( ( MockResult )result );
        }
      }
    }
  }

  public MockResult dispatchGetRequest( HttpServletRequest request, HttpServletResponse response )
      throws DispatchException
  {
    try
    {
      String qs = request.getQueryString();
      if( qs != null && qs.toUpperCase().startsWith( "WSDL" ) )
      {
        dispatchWsdlRequest( request, response );
      }
      else
      {
        if( qs != null && qs.startsWith( "cmd=" ) )
        {
          dispatchCommand( request.getParameter( "cmd" ), request, response );
        }
        else
        {
          String docroot = PropertyExpander.expandProperties( mockContext, getMockService().getDocroot() );
          if( StringUtils.hasContent( docroot ) )
          {
            try
            {
              String pathInfo = request.getPathInfo();
              if( pathInfo == null )
                pathInfo = "";

              if( mockService.getPath().length() > 1 && pathInfo.startsWith( mockService.getPath() ) )
                pathInfo = pathInfo.substring( mockService.getPath().length() );

              String filename = docroot + pathInfo.replace( '/', File.separatorChar );
              File file = new File( filename );
              if( file.exists() )
              {
                returnFile( response, file );
              }
            }
            catch( Throwable e )
            {
              throw new DispatchException( e );
            }
          }
        }
      }

      return null;
    }
    catch( Exception e )
    {
      throw new DispatchException( e );
    }
  }

  public void returnFile( HttpServletResponse response, File file ) throws FileNotFoundException, IOException
  {
    FileInputStream in = new FileInputStream( file );
    response.setStatus( HttpServletResponse.SC_OK );
    long length = file.length();
    response.setContentLength( ( int )length );
    response.setContentType( ContentTypeHandler.getContentTypeFromFilename( file.getName() ) );
    Tools.readAndWrite( in, length, response.getOutputStream() );
    in.close();
  }

  private void dispatchCommand( String cmd, HttpServletRequest request, HttpServletResponse response )
      throws IOException
  {
    if( "stop".equals( cmd ) )
    {
      response.setStatus( HttpServletResponse.SC_OK );
      response.flushBuffer();

      SoapUI.getThreadPool().execute( new Runnable()
      {

        public void run()
        {
          try
          {
            Thread.sleep( 500 );
          }
          catch( InterruptedException e )
          {
            e.printStackTrace();
          }
          stop();
        }
      } );
    }
    else if( "restart".equals( cmd ) )
    {
      response.setStatus( HttpServletResponse.SC_OK );
      response.flushBuffer();

      SoapUI.getThreadPool().execute( new Runnable()
      {

        public void run()
        {
          try
          {
            Thread.sleep( 500 );
          }
          catch( InterruptedException e )
          {
            e.printStackTrace();
          }

          stop();
          //
          // try
          // {
          // Thread.sleep( 500 );
          // }
          // catch( InterruptedException e )
          // {
          // e.printStackTrace();
          // }

          try
          {
            mockService.start();
          }
          catch( Exception e )
          {
            e.printStackTrace();
          }

        }
      } );
    }
  }

  protected void dispatchWsdlRequest( HttpServletRequest request, HttpServletResponse response ) throws IOException
  {
    if( request.getQueryString().equalsIgnoreCase( "WSDL" ) )
    {
      printWsdl( response );
      return;
    }

    String ifaceName = request.getParameter( "interface" );
    WsdlInterface iface = ( WsdlInterface )mockService.getProject().getInterfaceByName( ifaceName );
    if( iface == null )
    {
      printInterfaceList( response );
      return;
    }

    StringToStringMap parts = wsdlCache.get( iface.getName() );
    String part = request.getParameter( "part" );
    String content = StringUtils.isNullOrEmpty( part ) ? null : parts.get( part );

    if( content == null )
    {
      printPartList( iface, parts, response );
      return;
    }

    if( content != null )
    {
      printOkXmlResult( response, content );
    }
  }

  public void printOkXmlResult( HttpServletResponse response, String content ) throws IOException
  {
    response.setStatus( HttpServletResponse.SC_OK );
    response.setContentType( "text/xml" );
    response.setCharacterEncoding( "UTF-8" );
    response.getWriter().print( content );
  }

  public void printWsdl( HttpServletResponse response ) throws IOException
  {
    WsdlInterface[] mockedInterfaces = mockService.getMockedInterfaces();
    if( mockedInterfaces.length == 1 )
    {
      StringToStringMap parts = wsdlCache.get( mockedInterfaces[0].getName() );
      printOkXmlResult( response, parts.get( parts.get( "#root#" ) ) );
    }
    else
    {
      try
      {
        WSDLFactory wsdlFactory = WSDLFactory.newInstance();
        Definition def = wsdlFactory.newDefinition();
        for( WsdlInterface iface : mockedInterfaces )
        {
          StringToStringMap parts = wsdlCache.get( iface.getName() );
          Import wsdlImport = def.createImport();
          wsdlImport.setLocationURI( getInterfacePrefix( iface ) + "&part=" + parts.get( "#root#" ) );
          wsdlImport.setNamespaceURI( WsdlUtils.getTargetNamespace( iface.getWsdlContext().getDefinition() ) );

          def.addImport( wsdlImport );
        }

        response.setStatus( HttpServletResponse.SC_OK );
        response.setContentType( "text/xml" );
        response.setCharacterEncoding( "UTF-8" );

        WSDLWriter writer = wsdlFactory.newWSDLWriter();
        writer.writeWSDL( def, response.getWriter() );
      }
      catch( Exception e )
      {
        SoapUI.logError( e );
        throw new IOException( "Failed to create combined WSDL" );
      }
    }
  }

  public void printPartList( WsdlInterface iface, StringToStringMap parts, HttpServletResponse response )
      throws IOException
  {
    response.setStatus( HttpServletResponse.SC_OK );
    response.setContentType( "text/html" );

    PrintWriter out = response.getWriter();
    out.print( "<html><body><p>Parts in interface [" + iface.getName() + "]</p><ul>" );

    for( String key : parts.keySet() )
    {
      if( key.equals( "#root#" ) )
        continue;

      out.print( "<li><a href=\"" );
      out.print( getInterfacePrefix( iface ) + "&part=" + key );
      out.print( "\">" + key + "</a></li>" );
    }

    out.print( "</ul></p></body></html>" );
  }

  public void printInterfaceList( HttpServletResponse response ) throws IOException
  {
    response.setStatus( HttpServletResponse.SC_OK );
    response.setContentType( "text/html" );

    PrintWriter out = response.getWriter();
    out.print( "<html><body><p>Mocked Interfaces in project [" + mockService.getProject().getName() + "]</p><ul>" );

    for( Interface iface : ModelSupport.getChildren( mockService.getProject(), WsdlInterface.class ) )
    {
      out.print( "<li><a href=\"" );
      out.print( getInterfacePrefix( iface ) );
      out.print( "\">" + iface.getName() + "</a></li>" );
    }

    out.print( "</ul></p></body></html>" );
  }

  public String getOverviewUrl()
  {
    return mockService.getPath() + "?WSDL";
  }

  public void setLogEnabled( boolean logEnabled )
  {
    this.logEnabled = logEnabled;
  }

  public void start() throws Exception
  {
    if( running )
      return;

    mockContext.reset();
    mockService.runStartScript( mockContext, this );

    SoapUI.getMockEngine().startMockService( this );
    running = true;

    MockRunListener[] mockRunListeners = mockService.getMockRunListeners();

    for( MockRunListener listener : mockRunListeners )
    {
      listener.onMockRunnerStart( this );
    }
  }
}
TOP

Related Classes of com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner

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.