1
2
3
4
5
6
7
8
9
10
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.xmlbeans.SimpleValue;
24 import org.apache.xmlbeans.XmlException;
25 import org.apache.xmlbeans.XmlObject;
26 import org.apache.xmlbeans.XmlOptions;
27 import org.w3c.dom.Node;
28
29 import com.eviware.soapui.config.DefinitionCacheConfig;
30 import com.eviware.soapui.config.DefinitionCacheTypeConfig;
31 import com.eviware.soapui.config.DefintionPartConfig;
32 import com.eviware.soapui.impl.support.AbstractInterface;
33 import com.eviware.soapui.impl.wsdl.support.Constants;
34 import com.eviware.soapui.impl.wsdl.support.PathUtils;
35 import com.eviware.soapui.support.Tools;
36 import com.eviware.soapui.support.types.StringToStringMap;
37 import com.eviware.soapui.support.xml.XmlUtils;
38
39 /***
40 * WsdlLoader for cached definitions
41 *
42 * @author ole.matzura
43 */
44
45 public class CachedWsdlLoader extends WsdlLoader
46 {
47 private final DefinitionCacheConfig config;
48 private String rootInConfig = "";
49
50 public CachedWsdlLoader( DefinitionCacheConfig config )
51 {
52 super( config.getRootPart() );
53 this.config = config;
54 }
55
56 public CachedWsdlLoader( AbstractInterface<?> iface ) throws Exception
57 {
58 this( WsdlUtils.cacheWsdl( new UrlWsdlLoader( PathUtils.expandPath( iface.getDefinition(), iface ), iface ) ) );
59 }
60
61 public InputStream load( String url ) throws Exception
62 {
63 XmlObject xmlObject = loadXmlObject( url, null );
64 return xmlObject == null ? null : xmlObject.newInputStream();
65 }
66
67 public XmlObject loadXmlObject( String url, XmlOptions options ) throws Exception
68 {
69
70 if( url.endsWith( config.getRootPart() ) )
71 {
72 rootInConfig = url.substring( 0, url.length() - config.getRootPart().length() );
73 }
74
75 List<DefintionPartConfig> partList = config.getPartList();
76 for( DefintionPartConfig part : partList )
77 {
78 if( ( rootInConfig + part.getUrl() ).equalsIgnoreCase( url ) )
79 {
80 return getPartContent( config, part );
81 }
82 }
83
84
85 if( File.separatorChar == '/' )
86 {
87 url = url.replace( '/', '//' );
88
89 for( DefintionPartConfig part : partList )
90 {
91 if( ( rootInConfig + part.getUrl() ).equalsIgnoreCase( url ) )
92 {
93 return getPartContent( config, part );
94 }
95 }
96 }
97
98 else if( File.separatorChar == '//' )
99 {
100 url = url.replace( '//', '/' );
101
102 for( DefintionPartConfig part : partList )
103 {
104 if( ( rootInConfig + part.getUrl() ).equalsIgnoreCase( url ) )
105 {
106 return getPartContent( config, part );
107 }
108 }
109 }
110
111 return null;
112 }
113
114 public static XmlObject getPartContent( DefinitionCacheConfig config, DefintionPartConfig part ) throws XmlException
115 {
116 if( config.getType() == DefinitionCacheTypeConfig.TEXT )
117 {
118 Node domNode = part.getContent().getDomNode();
119 String nodeValue = XmlUtils.getNodeValue( domNode );
120 return XmlObject.Factory.parse( nodeValue, new XmlOptions().setLoadLineNumbers() );
121 }
122
123 return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
124 }
125
126 /***
127 * Saves the complete definition to the specified folder, returns path to
128 * root part
129 *
130 * @param folderName
131 * @return
132 * @throws Exception
133 */
134
135 public String saveDefinition( String folderName ) throws Exception
136 {
137 File outFolder = new File( folderName );
138 if( !outFolder.exists() && !outFolder.mkdirs() )
139 throw new Exception( "Failed to create directory [" + folderName + "]" );
140
141 Map<String, String> urlToFileMap = new HashMap<String, String>();
142
143 setFilenameForUrl( config.getRootPart(), Constants.WSDL11_NS, urlToFileMap, null );
144
145 List<DefintionPartConfig> partList = config.getPartList();
146 for( DefintionPartConfig part : partList )
147 {
148 setFilenameForUrl( part.getUrl(), part.getType(), urlToFileMap, null );
149 }
150
151 for( DefintionPartConfig part : partList )
152 {
153 XmlObject obj = null;
154 if( config.getType() == DefinitionCacheTypeConfig.TEXT )
155 {
156 obj = XmlObject.Factory.parse( XmlUtils.getNodeValue( part.getContent().getDomNode() ) );
157 }
158 else
159 {
160 obj = XmlObject.Factory.parse( part.getContent().toString() );
161 }
162
163 replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
164 obj.save( new File( outFolder, urlToFileMap.get( part.getUrl() ) ) );
165 }
166
167 return folderName + File.separatorChar + urlToFileMap.get( config.getRootPart() );
168 }
169
170 public StringToStringMap createFilesForExport( String urlPrefix ) throws Exception
171 {
172 StringToStringMap result = new StringToStringMap();
173 Map<String, String> urlToFileMap = new HashMap<String, String>();
174
175 if( urlPrefix == null )
176 urlPrefix = "";
177
178 setFilenameForUrl( config.getRootPart(), Constants.WSDL11_NS, urlToFileMap, urlPrefix );
179
180 List<DefintionPartConfig> partList = config.getPartList();
181 for( DefintionPartConfig part : partList )
182 {
183 if( !part.getUrl().equals( config.getRootPart() ) )
184 setFilenameForUrl( part.getUrl(), part.getType(), urlToFileMap, urlPrefix );
185 }
186
187 for( DefintionPartConfig part : partList )
188 {
189 XmlObject obj = CachedWsdlLoader.getPartContent( config, part );
190 replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
191 String urlString = urlToFileMap.get( part.getUrl() );
192 if( urlString.startsWith( urlPrefix ) )
193 urlString = urlString.substring( urlPrefix.length() );
194
195 result.put( urlString, obj.xmlText() );
196
197 if( part.getUrl().equals( config.getRootPart() ) )
198 result.put( "#root#", obj.xmlText() );
199 }
200
201 return result;
202 }
203
204 private void setFilenameForUrl( String fileUrl, String type, Map<String, String> urlToFileMap, String urlPrefix )
205 throws MalformedURLException
206 {
207
208 String path = fileUrl;
209
210 try
211 {
212 URL url = new URL( fileUrl );
213 path = url.getPath();
214 }
215 catch( MalformedURLException e )
216 {
217 }
218
219 int ix = path.lastIndexOf( '/' );
220 String fileName = ix == -1 ? path : path.substring( ix + 1 );
221
222 ix = fileName.lastIndexOf( '.' );
223 if( ix != -1 )
224 fileName = fileName.substring( 0, ix );
225
226 if( type.equals( Constants.WSDL11_NS ) )
227 fileName += ".wsdl";
228 else if( type.equals( Constants.XSD_NS ) )
229 fileName += ".xsd";
230 else
231 fileName += ".xml";
232
233 if( urlPrefix != null )
234 fileName = urlPrefix + fileName;
235
236 int cnt = 1;
237 while( urlToFileMap.containsValue( fileName ) )
238 {
239 ix = fileName.lastIndexOf( '.' );
240 fileName = fileName.substring( 0, ix ) + "_" + cnt + fileName.substring( ix );
241 cnt++ ;
242 }
243
244 urlToFileMap.put( fileUrl, fileName );
245 }
246
247 private void replaceImportsAndIncludes( XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl )
248 throws Exception
249 {
250 XmlObject[] wsdlImports = xmlObject
251 .selectPath( "declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import/@location" );
252
253 for( int i = 0; i < wsdlImports.length; i++ )
254 {
255 SimpleValue wsdlImport = ( ( SimpleValue )wsdlImports[i] );
256 replaceLocation( urlToFileMap, baseUrl, wsdlImport );
257 }
258
259 XmlObject[] schemaImports = xmlObject
260 .selectPath( "declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation" );
261
262 for( int i = 0; i < schemaImports.length; i++ )
263 {
264 SimpleValue schemaImport = ( ( SimpleValue )schemaImports[i] );
265 replaceLocation( urlToFileMap, baseUrl, schemaImport );
266 }
267
268 XmlObject[] schemaIncludes = xmlObject
269 .selectPath( "declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation" );
270 for( int i = 0; i < schemaIncludes.length; i++ )
271 {
272 SimpleValue schemaInclude = ( ( SimpleValue )schemaIncludes[i] );
273 replaceLocation( urlToFileMap, baseUrl, schemaInclude );
274 }
275
276 XmlObject[] wadlImports = xmlObject.selectPath( "declare namespace s='" + Constants.WADL10_NS
277 + "' .//s:grammars/s:include/@href" );
278
279 for( int i = 0; i < wadlImports.length; i++ )
280 {
281 SimpleValue wadlImport = ( ( SimpleValue )wadlImports[i] );
282 replaceLocation( urlToFileMap, baseUrl, wadlImport );
283 }
284 }
285
286 private void replaceLocation( Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport )
287 throws Exception
288 {
289 String location = wsdlImport.getStringValue();
290 if( location != null )
291 {
292 if( location.startsWith( "file:" ) || location.indexOf( "://" ) > 0 )
293 {
294 String newLocation = urlToFileMap.get( location );
295 if( newLocation != null )
296 wsdlImport.setStringValue( newLocation );
297 else
298 throw new Exception( "Missing local file for [" + newLocation + "]" );
299 }
300 else
301 {
302 String loc = Tools.joinRelativeUrl( baseUrl, location );
303 String newLocation = urlToFileMap.get( loc );
304 if( newLocation != null )
305 wsdlImport.setStringValue( newLocation );
306 else
307 throw new Exception( "Missing local file for [" + loc + "]" );
308 }
309 }
310 }
311
312 public void close()
313 {
314 }
315 }