package com.bansheeproject;
import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.Service.Mode;
import com.bansheeproject.engine.BansheeDispatcher;
import com.bansheeproject.engine.JAXWSDispatcherImpl;
import com.bansheeproject.engine.wsdl.WSDLData;
import com.bansheeproject.engine.wsdl.WSDLRetriever;
import com.bansheeproject.engine.wsdl.WSDLRetrieverFactory;
import com.bansheeproject.exceptions.BansheeDispatcherCreationException;
import com.bansheeproject.exceptions.WSDLRetrievalException;
import com.bansheeproject.log.BansheeLogFactory;
import com.bansheeproject.log.BansheeLogger;
/**
* It represents service data provided by a WSDL.
*
* @author Alexandre Saudate
* @since 1.0
*/
public class WSDLServiceData extends ServiceData {
private String wsdlLocation;
private String targetNamespace;
private String serviceName;
private String portName;
private BansheeDispatcher cachedDispatcher;
private static BansheeLogger logger = BansheeLogFactory.getDefaultLogger(WSDLServiceData.class);
public WSDLServiceData(String wsdlLocation, String targetNamespace,
String serviceName, String portName) {
this(wsdlLocation, targetNamespace, serviceName, portName, false);
}
public WSDLServiceData(String wsdlLocation, String targetNamespace,
String serviceName, String portName, boolean eagerFetchWSDL) {
super();
StringBuilder builder = new StringBuilder();
builder.append("Initializing WSDL Service data: WSDLLocation - ");
builder.append(wsdlLocation);
builder.append(". Target namespace:");
builder.append(targetNamespace);
builder.append(". Service name:").append(serviceName);
builder.append(". Port name:").append(portName);
builder.append(". Eager fetch WSDL:").append(eagerFetchWSDL);
logger.debug(builder);
if (wsdlLocation == null) {
throw new IllegalArgumentException("WSDL location cannot be null.");
}
this.wsdlLocation = wsdlLocation;
this.targetNamespace = targetNamespace;
this.serviceName = serviceName;
this.portName = portName;
if (eagerFetchWSDL) {
cachedDispatcher = getDispatcher();
}
}
public static WSDLServiceData loadFromFile (File f ) throws WSDLRetrievalException {
return loadFromAddress(f.toURI().toASCIIString());
}
public static WSDLServiceData loadFromAddress (String address) throws WSDLRetrievalException{
logger.debug("Retrieving service data from address: ".concat(address));
WSDLRetriever retriever = WSDLRetrieverFactory.getInstance().getWSDLRetrieverInstance();
logger.debug(new StringBuilder("Instance of WSDLRetriever found: ").append(retriever));
WSDLData data = retriever.retrieveData(address);
String wsdlLocation = address;
String targetNamespace = data.getTargetNamespace();
if (data.getServices().size() != 1) {
throw new WSDLRetrievalException("WSDL has more than one service defined, so you have to build the WSDLServiceData manually, using the constructor provided.");
}
if (data.getServices().get(0).getPorts().size() != 1) {
throw new WSDLRetrievalException("Service has more than one port defined, so you have to build the WSDLServiceData manually, using the constructor provided.");
}
String serviceName = data.getServices().get(0).getServiceName().getLocalPart();
String portName = data.getServices().get(0).getPorts().get(0).getName();
WSDLServiceData serviceData = new WSDLServiceData(wsdlLocation, targetNamespace, serviceName, portName, true);
return serviceData;
}
@Override
public BansheeDispatcher getDispatcher() {
if (cachedDispatcher != null)
return cachedDispatcher;
try {
URL url = new URL(wsdlLocation);
Service service = Service.create(url, new QName(targetNamespace, serviceName));
Dispatch dispatcher = service.createDispatch(new QName(targetNamespace, portName ), SOAPMessage.class, Mode.MESSAGE);
JAXWSDispatcherImpl response = new JAXWSDispatcherImpl(dispatcher );
if (address != null) {
response.changeInvocationAddress(address);
}
return response;
} catch (Exception e) {
throw new BansheeDispatcherCreationException(e);
}
}
private String address;
@Override
public void setAddress(String address) {
this.address = address;
}
}