/*
* 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.support.definition.export;
import com.eviware.soapui.impl.rest.RestService;
import com.eviware.soapui.impl.support.definition.InterfaceDefinition;
import com.eviware.soapui.impl.support.definition.InterfaceDefinitionPart;
import com.eviware.soapui.impl.wsdl.support.Constants;
import com.eviware.soapui.model.iface.Interface;
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.XmlObject;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AbstractDefinitionExporter<T extends Interface> implements DefinitionExporter {
private InterfaceDefinition<T> definition;
public AbstractDefinitionExporter(InterfaceDefinition<T> definition) {
this.definition = definition;
}
public InterfaceDefinition<T> getDefinition() {
return definition;
}
public void setDefinition(InterfaceDefinition<T> definition) {
this.definition = definition;
}
public String export(String folderName) throws Exception {
if (definition.getDefinitionCache() == null || !definition.getDefinitionCache().validate()) {
throw new Exception("Definition is not cached for export");
}
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>();
setFilenameForPart(definition.getDefinitionCache().getRootPart(), urlToFileMap, null);
List<InterfaceDefinitionPart> partList = definition.getDefinitionCache().getDefinitionParts();
for (InterfaceDefinitionPart part : partList) {
setFilenameForPart(part, urlToFileMap, null);
}
for (InterfaceDefinitionPart part : partList) {
// XmlObject obj = XmlObject.Factory.parse( part.getContent() );
XmlObject obj = XmlUtils.createXmlObject(part.getContent());
replaceImportsAndIncludes(obj, urlToFileMap, part.getUrl());
postProcessing(obj, part);
obj.save(new File(outFolder, urlToFileMap.get(part.getUrl())));
}
return folderName + File.separatorChar
+ urlToFileMap.get(definition.getDefinitionCache().getRootPart().getUrl());
}
public StringToStringMap createFilesForExport(String urlPrefix) throws Exception {
StringToStringMap result = new StringToStringMap();
Map<String, String> urlToFileMap = new HashMap<String, String>();
if (urlPrefix == null) {
urlPrefix = "";
}
setFilenameForPart(definition.getDefinitionCache().getRootPart(), urlToFileMap, urlPrefix);
List<InterfaceDefinitionPart> partList = definition.getDefinitionCache().getDefinitionParts();
for (InterfaceDefinitionPart part : partList) {
if (!part.isRootPart()) {
setFilenameForPart(part, urlToFileMap, urlPrefix);
}
}
for (InterfaceDefinitionPart part : partList) {
// XmlObject obj = XmlObject.Factory.parse( part.getContent() );
XmlObject obj = XmlUtils.createXmlObject(part.getContent());
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.isRootPart()) {
result.put("#root#", urlString);
}
}
return result;
}
protected void postProcessing(XmlObject obj, InterfaceDefinitionPart part) {
}
private void setFilenameForPart(InterfaceDefinitionPart part, Map<String, String> urlToFileMap, String urlPrefix)
throws MalformedURLException {
String path = part.getUrl();
try {
URL url = new URL(path);
path = url.getPath();
} catch (MalformedURLException ignored) {
}
int ix = path.lastIndexOf('/');
if (ix == -1) {
ix = path.lastIndexOf('\\');
}
String fileName = ix == -1 ? path : path.substring(ix + 1);
ix = fileName.lastIndexOf('.');
if (ix != -1) {
fileName = fileName.substring(0, ix);
}
String type = part.getType();
if (type.equals(Constants.WSDL11_NS)) {
fileName += ".wsdl";
} else if (part.getType().equals(Constants.XSD_NS)) {
fileName += ".xsd";
} else if (getDefinition().getInterface() instanceof RestService
&& part.getType().equals(((RestService) getDefinition().getInterface()).getWadlVersion())) {
fileName += ".wadl";
} 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(part.getUrl(), fileName);
}
private void replaceImportsAndIncludes(XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl)
throws Exception {
String[] paths = getLocationXPathsToReplace();
for (String path : paths) {
XmlObject[] locations = xmlObject.selectPath(path);
for (XmlObject location : locations) {
SimpleValue wsdlImport = ((SimpleValue) location);
replaceLocation(urlToFileMap, baseUrl, wsdlImport);
}
}
}
protected abstract String[] getLocationXPathsToReplace();
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) {
newLocation = urlToFileMap.get(loc.replaceAll("/", "\\\\"));
}
if (newLocation == null) {
newLocation = urlToFileMap.get(loc.replaceAll("\\\\", "/"));
}
if (newLocation != null) {
wsdlImport.setStringValue(newLocation);
} else {
throw new Exception("Missing local file for [" + loc + "]");
}
}
}
}
}