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 public class CachedWsdlLoader extends WsdlLoader
34 {
35 private HttpState state;
36 private final DefinitionCacheConfig config;
37
38 public CachedWsdlLoader(DefinitionCacheConfig config)
39 {
40 super( config.getRootPart() );
41 this.config = config;
42 }
43
44 public CachedWsdlLoader(String wsdlUrl) throws Exception
45 {
46 this( WsdlLoader.cacheWsdl( new UrlWsdlLoader( wsdlUrl )));
47 }
48
49 public InputStream load( String url ) throws Exception
50 {
51 XmlObject xmlObject = loadXmlObject( url, null );
52 return xmlObject == null ? null : xmlObject.newInputStream();
53 }
54
55 public XmlObject loadXmlObject(String url, XmlOptions options ) throws Exception
56 {
57 List<DefintionPartConfig> partList = config.getPartList();
58 for( DefintionPartConfig part : partList )
59 {
60 if( part.getUrl().equalsIgnoreCase( url ))
61 {
62 return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
63 }
64 }
65
66 return null;
67 }
68
69 public boolean abort()
70 {
71 return false;
72 }
73
74 public boolean isAborted()
75 {
76 return false;
77 }
78
79 public String saveDefinition( String folderName ) throws Exception
80 {
81 File outFolder = new File( folderName );
82 if( !outFolder.exists() && !outFolder.mkdirs() )
83 throw new Exception( "Failed to create directory [" + folderName + "]" );
84
85 Map<String,String> urlToFileMap = new HashMap<String,String>();
86
87 setFilenameForUrl( config.getRootPart(), Constants.WSDL11_NS, urlToFileMap );
88
89 List<DefintionPartConfig> partList = config.getPartList();
90 for( DefintionPartConfig part : partList )
91 {
92 setFilenameForUrl( part.getUrl(), part.getType(), urlToFileMap );
93 }
94
95 for( DefintionPartConfig part : partList )
96 {
97 XmlObject obj = XmlObject.Factory.parse( part.getContent().toString() );
98 replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
99 obj.save( new File( outFolder, urlToFileMap.get( part.getUrl() )));
100 }
101
102 return folderName + File.separatorChar + urlToFileMap.get( config.getRootPart() );
103 }
104
105 private void setFilenameForUrl( String fileUrl, String type, Map<String,String> urlToFileMap ) throws MalformedURLException
106 {
107 URL url = new URL( fileUrl );
108 String path = url.getPath();
109
110 int ix = path.lastIndexOf( '/' );
111 String fileName = ix == -1 ? path : path.substring( ix+1 );
112
113 ix = fileName.lastIndexOf( '.');
114 if( ix != -1 )
115 fileName = fileName.substring( 0 , ix );
116
117 if( type.equals( Constants.WSDL11_NS ))
118 fileName += ".wsdl";
119 else if( type.equals( Constants.XSD_NS ))
120 fileName += ".xsd";
121 else
122 fileName += ".xml";
123
124 while( urlToFileMap.containsValue( fileName ))
125 {
126 ix = fileName.lastIndexOf( '.');
127 fileName = fileName.substring( 0, ix ) + "_" + fileName.substring( ix );
128 }
129
130 urlToFileMap.put( fileUrl, fileName );
131 }
132
133 private void replaceImportsAndIncludes(XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl ) throws Exception
134 {
135 XmlObject[] wsdlImports = xmlObject
136 .selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import/@location");
137
138 for (int i = 0; i < wsdlImports.length; i++)
139 {
140 SimpleValue wsdlImport = ((SimpleValue) wsdlImports[i]);
141 replaceLocation(urlToFileMap, baseUrl, wsdlImport);
142 }
143
144 XmlObject[] schemaImports = xmlObject
145 .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation");
146
147 for (int i = 0; i < schemaImports.length; i++)
148 {
149 SimpleValue schemaImport = ((SimpleValue) schemaImports[i]);
150 replaceLocation(urlToFileMap, baseUrl, schemaImport);
151 }
152
153 XmlObject[] schemaIncludes = xmlObject
154 .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation");
155 for (int i = 0; i < schemaIncludes.length; i++)
156 {
157 SimpleValue schemaInclude = ((SimpleValue) schemaIncludes[i]);
158 replaceLocation(urlToFileMap, baseUrl, schemaInclude);
159 }
160 }
161
162 private void replaceLocation(Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport) throws Exception
163 {
164 String location = wsdlImport.getStringValue();
165 if (location != null)
166 {
167 if (location.startsWith("file:")
168 || location.indexOf("://") > 0)
169 {
170 String newLocation = urlToFileMap.get( location );
171 if( newLocation != null )
172 wsdlImport.setStringValue( newLocation);
173 else
174 throw new Exception( "Missing local file for [" + newLocation + "]" );
175 }
176 else
177 {
178 String loc = Tools.joinRelativeUrl(baseUrl, location);
179 String newLocation = urlToFileMap.get( loc);
180 if( newLocation != null )
181 wsdlImport.setStringValue( newLocation);
182 else
183 throw new Exception( "Missing local file for [" + loc + "]" );
184 }
185 }
186 }
187
188 public void close()
189 {
190 }
191 }