View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 eviware.com
    3    *
    4    *  soapUI is free software; you can redistribute it and/or modify it under the
    5    *  terms of version 2.1 of the GNU Lesser General Public License as published by
    6    *  the Free Software Foundation.
    7    *
    8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
    9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    10   *  See the GNU Lesser General Public License for more details at gnu.org.
    11   */
    12
    13  package com.eviware.soapui.impl.wsdl.support.wsdl;
    14
    15  import java.io.File;
    16  import java.io.InputStream;
    17  import java.net.MalformedURLException;
    18  import java.net.URL;
    19  import java.util.HashMap;
    20  import java.util.List;
    21  import java.util.Map;
    22
    23  import org.apache.commons.httpclient.HttpState;
    24  import org.apache.xmlbeans.SimpleValue;
    25  import org.apache.xmlbeans.XmlObject;
    26  import org.apache.xmlbeans.XmlOptions;
    27
    28  import com.eviware.soapui.config.DefinitionCacheConfig;
    29  import com.eviware.soapui.config.DefintionPartConfig;
    30  import com.eviware.soapui.impl.wsdl.support.Constants;
    31  import com.eviware.soapui.support.Tools;
    32
    33  /***
    34   * WsdlLoader for cached definitions
    35   *
    36   * @author ole.matzura
    37   */
    38
    39  public class CachedWsdlLoader extends WsdlLoader
    40  {
    41  	@SuppressWarnings( "unused" )
    42  	private HttpState state;
    43  	private final DefinitionCacheConfig config;
    44
    45  	public CachedWsdlLoader( DefinitionCacheConfig config )
    46  	{
    47  		super( config.getRootPart() );
    48  		this.config = config;
    49  	}
    50
    51  	public CachedWsdlLoader( String wsdlUrl ) throws Exception
    52  	{
    53  		this( WsdlLoader.cacheWsdl( new UrlWsdlLoader( wsdlUrl ) ) );
    54  	}
    55
    56  	public InputStream load( String url ) throws Exception
    57  	{
    58  		XmlObject xmlObject = loadXmlObject( url, null );
    59  		return xmlObject == null ? null : xmlObject.newInputStream();
    60  	}
    61
    62  	public XmlObject loadXmlObject( String url, XmlOptions options ) throws Exception
    63  	{
    64  		List<DefintionPartConfig> partList = config.getPartList();
    65  		for( DefintionPartConfig part : partList )
    66  		{
    67  			if( part.getUrl().equalsIgnoreCase( url ) )
    68  			{
    69  				return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
    70  			}
    71  		}
    72
    73  		// hack: this could be due to windows -> unix, try again with replaced '/'
    74  		if( File.separatorChar == '/' )
    75  		{
    76  			url = url.replace( '/', '//' );
    77
    78  			for( DefintionPartConfig part : partList )
    79  			{
    80  				if( part.getUrl().equalsIgnoreCase( url ) )
    81  				{
    82  					return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
    83  				}
    84  			}
    85  		}
    86  		// or the other way around..
    87  		else if( File.separatorChar == '//' )
    88  		{
    89  			url = url.replace( '//', '/' );
    90
    91  			for( DefintionPartConfig part : partList )
    92  			{
    93  				if( part.getUrl().equalsIgnoreCase( url ) )
    94  				{
    95  					return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
    96  				}
    97  			}
    98  		}
    99
    100 		return null;
    101 	}
    102
    103 	public boolean abort()
    104 	{
    105 		return false;
    106 	}
    107
    108 	public boolean isAborted()
    109 	{
    110 		return false;
    111 	}
    112
    113 	public String saveDefinition( String folderName ) throws Exception
    114 	{
    115 		File outFolder = new File( folderName );
    116 		if( !outFolder.exists() && !outFolder.mkdirs() )
    117 			throw new Exception( "Failed to create directory [" + folderName + "]" );
    118
    119 		Map<String, String> urlToFileMap = new HashMap<String, String>();
    120
    121 		setFilenameForUrl( config.getRootPart(), Constants.WSDL11_NS, urlToFileMap );
    122
    123 		List<DefintionPartConfig> partList = config.getPartList();
    124 		for( DefintionPartConfig part : partList )
    125 		{
    126 			setFilenameForUrl( part.getUrl(), part.getType(), urlToFileMap );
    127 		}
    128
    129 		for( DefintionPartConfig part : partList )
    130 		{
    131 			XmlObject obj = XmlObject.Factory.parse( part.getContent().toString() );
    132 			replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
    133 			obj.save( new File( outFolder, urlToFileMap.get( part.getUrl() ) ) );
    134 		}
    135
    136 		return folderName + File.separatorChar + urlToFileMap.get( config.getRootPart() );
    137 	}
    138
    139 	private void setFilenameForUrl( String fileUrl, String type, Map<String, String> urlToFileMap )
    140 				throws MalformedURLException
    141 	{
    142 		URL url = new URL( fileUrl );
    143 		String path = url.getPath();
    144
    145 		int ix = path.lastIndexOf( '/' );
    146 		String fileName = ix == -1 ? path : path.substring( ix + 1 );
    147
    148 		ix = fileName.lastIndexOf( '.' );
    149 		if( ix != -1 )
    150 			fileName = fileName.substring( 0, ix );
    151
    152 		if( type.equals( Constants.WSDL11_NS ) )
    153 			fileName += ".wsdl";
    154 		else if( type.equals( Constants.XSD_NS ) )
    155 			fileName += ".xsd";
    156 		else
    157 			fileName += ".xml";
    158
    159 		while( urlToFileMap.containsValue( fileName ) )
    160 		{
    161 			ix = fileName.lastIndexOf( '.' );
    162 			fileName = fileName.substring( 0, ix ) + "_" + fileName.substring( ix );
    163 		}
    164
    165 		urlToFileMap.put( fileUrl, fileName );
    166 	}
    167
    168 	private void replaceImportsAndIncludes( XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl )
    169 				throws Exception
    170 	{
    171 		XmlObject[] wsdlImports = xmlObject
    172 					.selectPath( "declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import/@location" );
    173
    174 		for( int i = 0; i < wsdlImports.length; i++ )
    175 		{
    176 			SimpleValue wsdlImport = ( ( SimpleValue ) wsdlImports[i] );
    177 			replaceLocation( urlToFileMap, baseUrl, wsdlImport );
    178 		}
    179
    180 		XmlObject[] schemaImports = xmlObject
    181 					.selectPath( "declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation" );
    182
    183 		for( int i = 0; i < schemaImports.length; i++ )
    184 		{
    185 			SimpleValue schemaImport = ( ( SimpleValue ) schemaImports[i] );
    186 			replaceLocation( urlToFileMap, baseUrl, schemaImport );
    187 		}
    188
    189 		XmlObject[] schemaIncludes = xmlObject
    190 					.selectPath( "declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation" );
    191 		for( int i = 0; i < schemaIncludes.length; i++ )
    192 		{
    193 			SimpleValue schemaInclude = ( ( SimpleValue ) schemaIncludes[i] );
    194 			replaceLocation( urlToFileMap, baseUrl, schemaInclude );
    195 		}
    196 	}
    197
    198 	private void replaceLocation( Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport )
    199 				throws Exception
    200 	{
    201 		String location = wsdlImport.getStringValue();
    202 		if( location != null )
    203 		{
    204 			if( location.startsWith( "file:" ) || location.indexOf( "://" ) > 0 )
    205 			{
    206 				String newLocation = urlToFileMap.get( location );
    207 				if( newLocation != null )
    208 					wsdlImport.setStringValue( newLocation );
    209 				else
    210 					throw new Exception( "Missing local file for [" + newLocation + "]" );
    211 			}
    212 			else
    213 			{
    214 				String loc = Tools.joinRelativeUrl( baseUrl, location );
    215 				String newLocation = urlToFileMap.get( loc );
    216 				if( newLocation != null )
    217 					wsdlImport.setStringValue( newLocation );
    218 				else
    219 					throw new Exception( "Missing local file for [" + loc + "]" );
    220 			}
    221 		}
    222 	}
    223
    224 	public void close()
    225 	{
    226 	}
    227 }