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