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