/*
* 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.SoapUI;
import com.eviware.soapui.config.WsaVersionTypeConfig;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.BindingImporter;
import com.eviware.soapui.impl.wsdl.support.policy.PolicyUtils;
import com.eviware.soapui.impl.wsdl.support.soap.Soap11HttpBindingImporter;
import com.eviware.soapui.impl.wsdl.support.soap.Soap12HttpBindingImporter;
import com.eviware.soapui.impl.wsdl.support.soap.SoapJMSBindingImporter;
import com.eviware.soapui.impl.wsdl.support.soap.TibcoSoapJMSBindingImporter;
import com.eviware.soapui.settings.WsdlSettings;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.UISupport;
import org.apache.log4j.Logger;
import javax.wsdl.Binding;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Importer for WsdlInterfaces from WSDL urls / files
*
* @author Ole.Matzura
*/
public class WsdlImporter {
private static List<BindingImporter> bindingImporters = new ArrayList<BindingImporter>();
@SuppressWarnings("unused")
private static WsdlImporter instance;
private final static Logger log = Logger.getLogger(WsdlImporter.class);
static {
try {
bindingImporters.add(new Soap11HttpBindingImporter());
bindingImporters.add(new Soap12HttpBindingImporter());
bindingImporters.add(new SoapJMSBindingImporter());
bindingImporters.add(new TibcoSoapJMSBindingImporter());
} catch (Exception e) {
SoapUI.logError(e);
}
}
public static WsdlInterface[] importWsdl(WsdlProject project, String wsdlUrl) throws Exception {
return importWsdl(project, wsdlUrl, null);
}
public static WsdlInterface[] importWsdl(WsdlProject project, String wsdlUrl, QName bindingName) throws Exception {
return importWsdl(project, wsdlUrl, bindingName, null);
}
public static WsdlInterface[] importWsdl(WsdlProject project, String wsdlUrl, QName bindingName,
WsdlLoader wsdlLoader) throws Exception {
wsdlUrl = Tools.normalizeFileSeparators(wsdlUrl);
WsdlContext wsdlContext = new WsdlContext(wsdlUrl);
if (!wsdlContext.load(wsdlLoader)) {
UISupport.showErrorMessage("Failed to import WSDL");
return null;
}
Definition definition = wsdlContext.getDefinition();
List<WsdlInterface> result = new ArrayList<WsdlInterface>();
if (bindingName != null) {
WsdlInterface iface = importBinding(project, wsdlContext,
(Binding) definition.getAllBindings().get(bindingName));
return iface == null ? new WsdlInterface[0] : new WsdlInterface[]{iface};
}
Map<Binding, WsdlInterface> importedBindings = new HashMap<Binding, WsdlInterface>();
Map<?, ?> serviceMap = definition.getAllServices();
if (serviceMap.isEmpty()) {
log.info("Missing services in [" + wsdlUrl + "], check for bindings");
} else {
Iterator<?> i = serviceMap.values().iterator();
while (i.hasNext()) {
Service service = (Service) i.next();
Map<?, ?> portMap = service.getPorts();
Iterator<?> i2 = portMap.values().iterator();
while (i2.hasNext()) {
Port port = (Port) i2.next();
Binding binding = port.getBinding();
if (importedBindings.containsKey(binding)) {
// add endpoint since it could differ from already imported
// one..
String endpoint = WsdlUtils.getSoapEndpoint(port);
if (endpoint != null) {
importedBindings.get(binding).addEndpoint(endpoint);
}
continue;
}
String ifaceName = getInterfaceNameForBinding(binding);
WsdlInterface ifc = (WsdlInterface) project.getInterfaceByName(ifaceName);
if (ifc != null) {
Boolean res = UISupport.confirmOrCancel("Interface [" + ifc.getName()
+ "] already exists in project, update instead?", "Import WSDL");
if (res == null) {
return new WsdlInterface[0];
}
if (res.booleanValue()) {
if (ifc.updateDefinition(wsdlUrl, false)) {
importedBindings.put(binding, ifc);
result.add(ifc);
}
}
continue;
}
WsdlInterface iface = importBinding(project, wsdlContext, binding);
if (iface != null) {
String endpoint = WsdlUtils.getSoapEndpoint(port);
if (endpoint != null) {
iface.addEndpoint(endpoint);
}
// NOTE: question is what has priority wsaw:usingAddressing or
// wsam:Addressing policy
// in case addressing is defined both ways in the wsdl and
// there is conflict
// currently the first one that's set is final
// first is checked wsdl binding and policy attachment
// and then for port in the same order
if (iface.getWsaVersion().equals(WsaVersionTypeConfig.NONE.toString())) {
iface.setWsaVersion(WsdlUtils.getUsingAddressing(port));
}
if (iface.getWsaVersion().equals(WsaVersionTypeConfig.NONE.toString())) {
iface.processPolicy(PolicyUtils.getAttachedPolicy(port, wsdlContext.getDefinition()));
}
result.add(iface);
importedBindings.put(binding, iface);
}
}
}
}
Map<?, ?> bindingMap = definition.getAllBindings();
if (!bindingMap.isEmpty()) {
Iterator<?> i = bindingMap.values().iterator();
while (i.hasNext()) {
Binding binding = (Binding) i.next();
if (importedBindings.containsKey(binding)) {
continue;
}
PortType portType = binding.getPortType();
if (portType == null) {
log.warn("Missing portType for binding [" + binding.getQName().toString() + "]");
} else {
String ifaceName = getInterfaceNameForBinding(binding);
WsdlInterface ifc = (WsdlInterface) project.getInterfaceByName(ifaceName);
if (ifc != null && result.indexOf(ifc) == -1) {
Boolean res = UISupport.confirmOrCancel("Interface [" + ifc.getName()
+ "] already exists in project, update instead?", "Import WSDL");
if (res == null) {
return new WsdlInterface[0];
}
if (res.booleanValue()) {
if (ifc.updateDefinition(wsdlUrl, false)) {
importedBindings.put(binding, ifc);
result.add(ifc);
}
}
continue;
}
WsdlInterface iface = importBinding(project, wsdlContext, binding);
if (iface != null) {
result.add(iface);
importedBindings.put(binding, ifc);
}
}
}
}
if (importedBindings.isEmpty() && serviceMap.isEmpty() && bindingMap.isEmpty()) {
UISupport.showErrorMessage("Found nothing to import in [" + wsdlUrl + "]");
}
// only the last gets the context
if (result.size() > 0) {
result.get(result.size() - 1).setWsdlContext(wsdlContext);
}
return result.toArray(new WsdlInterface[result.size()]);
}
public final static String getInterfaceNameForBinding(Binding binding) {
if (SoapUI.getSettings().getBoolean(WsdlSettings.NAME_WITH_BINDING)) {
return binding.getQName().getLocalPart();
} else {
return binding.getPortType().getQName().getLocalPart();
}
}
private static WsdlInterface importBinding(WsdlProject project, WsdlContext wsdlContext, Binding binding)
throws Exception {
log.info("Finding importer for " + binding.getQName());
for (int c = 0; c < bindingImporters.size(); c++) {
BindingImporter importer = bindingImporters.get(c);
if (importer.canImport(binding)) {
log.info("Importing binding " + binding.getQName());
WsdlInterface iface = importer.importBinding(project, wsdlContext, binding);
String url = wsdlContext.getUrl();
iface.setDefinition(url);
return iface;
}
}
log.info("Missing importer for " + binding.getQName());
return null;
}
}