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.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
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
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 }