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 }