/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.support.wsdl; import com.eviware.soapui.config.DefinitionCacheConfig; import com.eviware.soapui.config.DefinitionCacheTypeConfig; import com.eviware.soapui.config.DefintionPartConfig; import com.eviware.soapui.impl.support.AbstractInterface; import com.eviware.soapui.impl.wsdl.support.Constants; import com.eviware.soapui.impl.wsdl.support.PathUtils; import com.eviware.soapui.support.Tools; import com.eviware.soapui.support.types.StringToStringMap; import com.eviware.soapui.support.xml.XmlUtils; import org.apache.xmlbeans.SimpleValue; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; import org.w3c.dom.Node; import java.io.File; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; /** * WsdlLoader for cached definitions * * @author ole.matzura */ public class CachedWsdlLoader extends WsdlLoader { private final DefinitionCacheConfig config; private String rootInConfig = ""; public CachedWsdlLoader(DefinitionCacheConfig config) { super(config.getRootPart()); this.config = config; } public CachedWsdlLoader(AbstractInterface<?> iface) throws Exception { this(WsdlUtils.cacheWsdl(new UrlWsdlLoader(PathUtils.expandPath(iface.getDefinition(), iface), iface))); } public InputStream load(String url) throws Exception { XmlObject xmlObject = loadXmlObject(url, null); return xmlObject == null ? null : xmlObject.newInputStream(); } public XmlObject loadXmlObject(String url, XmlOptions options) throws Exception { // required for backwards compatibility when the entire path was stored if (url.endsWith(config.getRootPart())) { rootInConfig = url.substring(0, url.length() - config.getRootPart().length()); } List<DefintionPartConfig> partList = config.getPartList(); for (DefintionPartConfig part : partList) { if ((rootInConfig + part.getUrl()).equalsIgnoreCase(url)) { return getPartContent(config, part); } } // hack: this could be due to windows -> unix, try again with replaced '/' if (File.separatorChar == '/') { url = url.replace('/', '\\'); for (DefintionPartConfig part : partList) { if ((rootInConfig + part.getUrl()).equalsIgnoreCase(url)) { return getPartContent(config, part); } } } // or the other way around.. else if (File.separatorChar == '\\') { url = url.replace('\\', '/'); for (DefintionPartConfig part : partList) { if ((rootInConfig + part.getUrl()).equalsIgnoreCase(url)) { return getPartContent(config, part); } } } return null; } public static XmlObject getPartContent(DefinitionCacheConfig config, DefintionPartConfig part) throws XmlException { if (config.getType() == DefinitionCacheTypeConfig.TEXT) { Node domNode = part.getContent().getDomNode(); String nodeValue = XmlUtils.getNodeValue(domNode); // return XmlObject.Factory.parse( nodeValue, new // XmlOptions().setLoadLineNumbers() ); return XmlUtils.createXmlObject(nodeValue, new XmlOptions().setLoadLineNumbers()); } // return XmlObject.Factory.parse( part.getContent().toString(), new // XmlOptions().setLoadLineNumbers() ); return XmlUtils.createXmlObject(part.getContent().toString(), new XmlOptions().setLoadLineNumbers()); } /** * Saves the complete definition to the specified folder, returns path to * root part * * @param folderName * @return * @throws Exception */ public String saveDefinition(String folderName) throws Exception { File outFolder = new File(folderName); if (!outFolder.exists() && !outFolder.mkdirs()) { throw new Exception("Failed to create directory [" + folderName + "]"); } Map<String, String> urlToFileMap = new HashMap<String, String>(); setFilenameForUrl(config.getRootPart(), Constants.WSDL11_NS, urlToFileMap, null); List<DefintionPartConfig> partList = config.getPartList(); for (DefintionPartConfig part : partList) { setFilenameForUrl(part.getUrl(), part.getType(), urlToFileMap, null); } for (DefintionPartConfig part : partList) { XmlObject obj = null; if (config.getType() == DefinitionCacheTypeConfig.TEXT) { // obj = XmlObject.Factory.parse( XmlUtils.getNodeValue( // part.getContent().getDomNode() ) ); obj = XmlUtils.createXmlObject(XmlUtils.getNodeValue(part.getContent().getDomNode())); } else { // obj = XmlObject.Factory.parse( part.getContent().toString() ); obj = XmlUtils.createXmlObject(part.getContent().toString()); } replaceImportsAndIncludes(obj, urlToFileMap, part.getUrl()); obj.save(new File(outFolder, urlToFileMap.get(part.getUrl()))); } return folderName + File.separatorChar + urlToFileMap.get(config.getRootPart()); } public StringToStringMap createFilesForExport(String urlPrefix) throws Exception { StringToStringMap result = new StringToStringMap(); Map<String, String> urlToFileMap = new HashMap<String, String>(); if (urlPrefix == null) { urlPrefix = ""; } setFilenameForUrl(config.getRootPart(), Constants.WSDL11_NS, urlToFileMap, urlPrefix); List<DefintionPartConfig> partList = config.getPartList(); for (DefintionPartConfig part : partList) { if (!part.getUrl().equals(config.getRootPart())) { setFilenameForUrl(part.getUrl(), part.getType(), urlToFileMap, urlPrefix); } } for (DefintionPartConfig part : partList) { XmlObject obj = CachedWsdlLoader.getPartContent(config, part); replaceImportsAndIncludes(obj, urlToFileMap, part.getUrl()); String urlString = urlToFileMap.get(part.getUrl()); if (urlString.startsWith(urlPrefix)) { urlString = urlString.substring(urlPrefix.length()); } result.put(urlString, obj.xmlText()); if (part.getUrl().equals(config.getRootPart())) { result.put("#root#", obj.xmlText()); } } return result; } private void setFilenameForUrl(String fileUrl, String type, Map<String, String> urlToFileMap, String urlPrefix) throws MalformedURLException { String path = fileUrl; try { URL url = new URL(fileUrl); path = url.getPath(); } catch (MalformedURLException e) { } int ix = path.lastIndexOf('/'); String fileName = ix == -1 ? path : path.substring(ix + 1); ix = fileName.lastIndexOf('.'); if (ix != -1) { fileName = fileName.substring(0, ix); } if (type.equals(Constants.WSDL11_NS)) { fileName += ".wsdl"; } else if (type.equals(Constants.XSD_NS)) { fileName += ".xsd"; } else { fileName += ".xml"; } if (urlPrefix != null) { fileName = urlPrefix + fileName; } int cnt = 1; while (urlToFileMap.containsValue(fileName)) { ix = fileName.lastIndexOf('.'); fileName = fileName.substring(0, ix) + "_" + cnt + fileName.substring(ix); cnt++; } urlToFileMap.put(fileUrl, fileName); } private void replaceImportsAndIncludes(XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl) throws Exception { XmlObject[] wsdlImports = xmlObject .selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import/@location"); for (int i = 0; i < wsdlImports.length; i++) { SimpleValue wsdlImport = ((SimpleValue) wsdlImports[i]); replaceLocation(urlToFileMap, baseUrl, wsdlImport); } XmlObject[] schemaImports = xmlObject .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation"); for (int i = 0; i < schemaImports.length; i++) { SimpleValue schemaImport = ((SimpleValue) schemaImports[i]); replaceLocation(urlToFileMap, baseUrl, schemaImport); } XmlObject[] schemaIncludes = xmlObject .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation"); for (int i = 0; i < schemaIncludes.length; i++) { SimpleValue schemaInclude = ((SimpleValue) schemaIncludes[i]); replaceLocation(urlToFileMap, baseUrl, schemaInclude); } XmlObject[] wadlImports = xmlObject.selectPath("declare namespace s='" + Constants.WADL10_NS + "' .//s:grammars/s:include/@href"); for (int i = 0; i < wadlImports.length; i++) { SimpleValue wadlImport = ((SimpleValue) wadlImports[i]); replaceLocation(urlToFileMap, baseUrl, wadlImport); } wadlImports = xmlObject.selectPath("declare namespace s='" + Constants.WADL11_NS + "' .//s:grammars/s:include/@href"); for (int i = 0; i < wadlImports.length; i++) { SimpleValue wadlImport = ((SimpleValue) wadlImports[i]); replaceLocation(urlToFileMap, baseUrl, wadlImport); } } private void replaceLocation(Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport) throws Exception { String location = wsdlImport.getStringValue(); if (location != null) { if (location.startsWith("file:") || location.indexOf("://") > 0) { String newLocation = urlToFileMap.get(location); if (newLocation != null) { wsdlImport.setStringValue(newLocation); } else { throw new Exception("Missing local file for [" + newLocation + "]"); } } else { String loc = Tools.joinRelativeUrl(baseUrl, location); String newLocation = urlToFileMap.get(loc); if (newLocation != null) { wsdlImport.setStringValue(newLocation); } else { throw new Exception("Missing local file for [" + loc + "]"); } } } } public void close() { } }