package org.codehaus.xfire.service.binding;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.xml.namespace.QName;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.XFireFactory;
import org.codehaus.xfire.XFireRuntimeException;
import org.codehaus.xfire.exchange.MessageSerializer;
import org.codehaus.xfire.fault.FaultInfoException;
import org.codehaus.xfire.fault.FaultSender;
import org.codehaus.xfire.fault.SoapFaultSerializer;
import org.codehaus.xfire.fault.XFireFault;
import org.codehaus.xfire.handler.CustomFaultHandler;
import org.codehaus.xfire.handler.OutMessageSender;
import org.codehaus.xfire.service.Binding;
import org.codehaus.xfire.service.Endpoint;
import org.codehaus.xfire.service.FaultInfo;
import org.codehaus.xfire.service.MessageInfo;
import org.codehaus.xfire.service.MessagePartContainer;
import org.codehaus.xfire.service.MessagePartInfo;
import org.codehaus.xfire.service.OperationInfo;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.ServiceFactory;
import org.codehaus.xfire.service.ServiceInfo;
import org.codehaus.xfire.service.invoker.ObjectInvoker;
import org.codehaus.xfire.service.invoker.ScopePolicyEditor;
import org.codehaus.xfire.soap.AbstractSoapBinding;
import org.codehaus.xfire.soap.Soap11Binding;
import org.codehaus.xfire.soap.Soap12Binding;
import org.codehaus.xfire.soap.SoapConstants;
import org.codehaus.xfire.soap.SoapTransport;
import org.codehaus.xfire.transport.Transport;
import org.codehaus.xfire.transport.TransportManager;
import org.codehaus.xfire.transport.http.SoapHttpTransport;
import org.codehaus.xfire.transport.local.LocalTransport;
import org.codehaus.xfire.util.ClassLoaderUtils;
import org.codehaus.xfire.util.MethodComparator;
import org.codehaus.xfire.util.NamespaceHelper;
import org.codehaus.xfire.util.ServiceUtils;
import org.codehaus.xfire.wsdl.LocatorWSDL;
import org.codehaus.xfire.wsdl11.DefinitionWSDL;
import org.codehaus.xfire.wsdl11.builder.DefaultWSDLBuilderFactory;
import org.codehaus.xfire.wsdl11.builder.WSDLBuilderAdapter;
import org.codehaus.xfire.wsdl11.builder.WSDLBuilderFactory;
import org.codehaus.xfire.wsdl11.parser.WSDLServiceConfigurator;
import org.xml.sax.InputSource;
/**
* Creates Services from java objects. This class is meant to be easily overridable
* so you can customize how your services are created.
*
* @author Dan Diephouse
* @author Arjen Poutsma
*/
public class ObjectServiceFactory
implements ServiceFactory
{
public static final String PORT_TYPE = "objectServiceFactory.portType";
public static final String PORT_NAME = "objectServiceFactory.portName";
public static final String STYLE = "objectServiceFactory.style";
public static final String USE = "objectServiceFactory.use";
public static final String CREATE_DEFAULT_BINDINGS = "objectServiceFactory.createDefaultBindings";
public static final String SOAP11_TRANSPORTS = "objectServiceFactory.soap11Transports";
public static final String SOAP12_TRANSPORTS = "objectServiceFactory.soap12Transports";
public static final String SCOPE = "objectServiceFactory.scope";
public static final String SCHEMAS = "objectServiceFactory.schemas";
private BindingProvider bindingProvider;
private TransportManager transportManager;
private String style;
private String use;
private Set ignoredClasses = new HashSet();
private boolean voidOneWay;
private WSDLBuilderFactory wsdlBuilderFactory = new DefaultWSDLBuilderFactory();
private boolean customFaultsEnabled = true;
private boolean bindingCreationEnabled = true;
private Set soap11Transports = new HashSet();
private Set soap12Transports = new HashSet();
private List serviceConfigurations = new ArrayList();
/**
* Initializes a new instance of the ObjectServiceFactory.
* Uses the XFireFactory to obtain an instance of the TransportManager.
*/
public ObjectServiceFactory()
{
this(XFireFactory.newInstance().getXFire().getTransportManager());
}
/**
* Initializes a new instance of the ObjectServiceFactory with the given transport manager and type
* mapping registry.
*
* @param transportManager the transport manager
* @param provider the binding provider
*/
public ObjectServiceFactory(TransportManager transportManager, BindingProvider provider)
{
this(transportManager);
this.bindingProvider = provider;
}
/**
* Initializes a new instance of the ObjectServiceFactory.
*/
public ObjectServiceFactory(TransportManager transportManager)
{
this.transportManager = transportManager;
setStyle(SoapConstants.STYLE_WRAPPED);
setUse(SoapConstants.USE_LITERAL);
DefaultServiceConfiguration config = new DefaultServiceConfiguration();
config.setServiceFactory(this);
serviceConfigurations.add(config);
soap11Transports.add(SoapHttpTransport.SOAP11_HTTP_BINDING);
soap11Transports.add(LocalTransport.BINDING_ID);
soap12Transports.add(LocalTransport.BINDING_ID);
ignoredClasses.add("java.lang.Object");
ignoredClasses.add("java.lang.Throwable");
ignoredClasses.add("org.omg.CORBA_2_3.portable.ObjectImpl");
ignoredClasses.add("org.omg.CORBA.portable.ObjectImpl");
ignoredClasses.add("javax.ejb.EJBObject");
ignoredClasses.add("javax.rmi.CORBA.Stub");
}
public ObjectServiceFactory(BindingProvider bp)
{
this(XFireFactory.newInstance().getXFire().getTransportManager(), bp);
}
public BindingProvider getBindingProvider()
{
if (bindingProvider == null)
{
try
{
bindingProvider = (BindingProvider) ClassLoaderUtils
.loadClass("org.codehaus.xfire.aegis.AegisBindingProvider", getClass()).newInstance();
}
catch (Exception e)
{
throw new XFireRuntimeException("Couldn't find a binding provider!", e);
}
}
return bindingProvider;
}
/**
* Creates a service via create(Class). It then configures
* the bindings and endpoints on the service via the WSDL.
*/
public Service create(Class clazz, QName name, URL wsdlUrl, Map properties)
{
try
{
return create(clazz,
name,
WSDLFactory.newInstance().newWSDLReader().readWSDL(new LocatorWSDL( null, new InputSource(wsdlUrl.openStream()))),
// WSDLFactory.newInstance().newWSDLReader().readWSDL(null, new InputSource(wsdlUrl.openStream())),
properties);
}
catch (WSDLException e)
{
throw new XFireRuntimeException("Could not load WSDL.", e);
}
catch (IOException e)
{
throw new XFireRuntimeException("Could not load WSDL.", e);
}
}
public Service create(Class clazz, QName name, Definition def, Map properties)
{
if (properties == null) properties = new HashMap();
properties.put(CREATE_DEFAULT_BINDINGS, Boolean.FALSE);
if (name == null)
{
Map services = def.getServices();
javax.wsdl.Service service = (javax.wsdl.Service) getOnlyElem(services);
if (service != null)
{
name = service.getQName();
}
}
Service service;
if (name != null)
service = create(clazz, name.getLocalPart(), name.getNamespaceURI(), properties);
else
service = create(clazz, properties);
if (name != null) service.setName(name);
service.setWSDLWriter(new DefinitionWSDL(def));
try
{
WSDLServiceConfigurator config = new WSDLServiceConfigurator(service, def, transportManager);
config.configure();
}
catch (Exception e)
{
if (e instanceof XFireRuntimeException)
throw (XFireRuntimeException) e;
throw new XFireRuntimeException("Couldn't configure service.", e);
}
for (Iterator itr = service.getBindings().iterator(); itr.hasNext();)
{
Binding b = (Binding) itr.next();
for (Iterator oitr = service.getServiceInfo().getOperations().iterator(); oitr.hasNext();)
{
OperationInfo op = (OperationInfo) oitr.next();
configureHeaders(service, op, b);
}
if (b instanceof AbstractSoapBinding)
{
b.setSerializer(getSerializer((AbstractSoapBinding) b));
}
service.getBindingProvider().initialize(service, b);
}
service.getBindingProvider().initialize(service);
return service;
}
/**
* Returns the only value in a Map
*
* @param map
* @return the only value in the map, if it contained exactly 1 key/value
* pair
* null, otherwise
*/
private Object getOnlyElem(Map map)
{
if (map.size() == 1)
{
Set keySet = map.keySet();
Iterator i = keySet.iterator();
return map.get(i.next());
}
else
{
return null;
}
}
protected void configureHeaders(Service service, OperationInfo op, Binding b)
{
Method method = op.getMethod();
Class[] paramClasses = method.getParameterTypes();
MessagePartContainer inHeaders = b.getHeaders(op.getInputMessage());
MessagePartContainer outHeaders = null;
if (op.hasOutput()) outHeaders = b.getHeaders(op.getOutputMessage());
for (int j = 0; j < paramClasses.length; j++)
{
if (!paramClasses[j].equals(MessageContext.class) && isHeader(method, j))
{
final QName q = getInParameterName(service, op, method, j, false);
if (isOutParam(method, j))
{
MessagePartInfo part = outHeaders.getMessagePart(q);
if (part == null)
throw new XFireRuntimeException("Could not find header " + q + " in wsdl for operation " + op.getName());
part.setTypeClass(paramClasses[j]);
part.setIndex(j);
part.setSchemaType(null);
}
if (isInParam(method, j))
{
MessagePartInfo part = inHeaders.getMessagePart(q);
if (part == null)
throw new XFireRuntimeException("Could not find header " + q + " in wsdl for operation " + op.getName());
part.setTypeClass(paramClasses[j]);
part.setIndex(j);
part.setSchemaType(null);
}
}
}
}
/**
* Creates a service from the specified class. The service name will be the
* unqualified class name. The namespace will be based on the package.
* The service will use soap version 1.1, wrapped style, and literal use.
*
* @param clazz
* The service class used to populate the operations and
* parameters. If the class is an interface, then the
* implementation class that implements that interface must be
* set via {@link Service#setProperty(String, Object)} with the
* property key being
* {@link org.codehaus.xfire.service.invoker.ObjectInvoker#SERVICE_IMPL_CLASS}
* @return The service.
*/
public Service create(Class clazz)
{
return create(clazz, (Map) null);
}
/**
* Creates a service from the specified class. The service name will be the
* unqualified class name. The namespace will be based on the package.
* The service will use soap version 1.1, wrapped style, and literal use.
*
* @param clazz
* The service class used to populate the operations and
* parameters. If the class is an interface, then the
* implementation class that implements that interface must be
* set via {@link Service#setProperty(String, Object)} with the
* property key being
* {@link org.codehaus.xfire.service.invoker.ObjectInvoker#SERVICE_IMPL_CLASS}
* @return The service.
*/
public Service create(Class clazz, Map properties)
{
return create(clazz, (String) null, (String) null, properties);
}
protected String makeServiceNameFromClassName(Class clazz)
{
return ServiceUtils.makeServiceNameFromClassName(clazz);
}
/**
* Creates a service from the specified class, soap version, style and use. The returned service will have a name
* based on the class name, and a namespace based on the class package.
*
null, and will be replaced with sensible defaults if so. See the specific
* parameters for more info.
*
* @param clazz The service class used to populate the operations and parameters.
* @param name The name of the service. If null, a name will be generated from the class
* name.
* @param namespace The default namespace of the service. If null, a namespace will be generated
* from the class package.
* @return The service.
*/
public Service create(Class clazz, String name, String namespace, Map properties)
{
String theName = (name != null) ? name : makeServiceNameFromClassName(clazz);
String theNamespace = (namespace != null) ? namespace : getTargetNamespace(clazz);
QName qName = new QName(theNamespace, theName);
String theStyle = null;
String theUse = null;
QName portType = null;
Collection s11Bindings = null;
Collection s12Bindings = null;
String theScope="";
if (properties != null)
{
theStyle = (String) properties.get(STYLE);
theUse = (String) properties.get(USE);
portType = (QName) properties.get(PORT_TYPE);
s11Bindings = (List) properties.get(SOAP11_TRANSPORTS);
s12Bindings = (List) properties.get(SOAP12_TRANSPORTS);
theScope = (String) properties.get(SCOPE);
}
if (theStyle == null) theStyle = style;
if (theUse == null) theUse = use;
if (portType == null) portType = new QName(theNamespace, theName + "PortType");
if (theScope == null) theScope = "";
ServiceInfo serviceInfo = new ServiceInfo(portType, clazz);
if (theStyle.equals(SoapConstants.STYLE_WRAPPED))
serviceInfo.setWrapped(true);
Service endpoint = new Service(serviceInfo);
endpoint.setName(qName);
setProperties(endpoint, properties);
final ObjectInvoker invoker = new ObjectInvoker(ScopePolicyEditor.toScopePolicy(theScope));
endpoint.setInvoker(invoker);
endpoint.setFaultSerializer(new SoapFaultSerializer());
endpoint.setWSDLWriter(new WSDLBuilderAdapter(getWsdlBuilderFactory(), endpoint, transportManager));
initializeOperations(endpoint, theStyle);
endpoint.setProperty(STYLE, theStyle);
endpoint.setProperty(USE, theUse);
boolean buildBindings = bindingCreationEnabled;
if (properties != null && properties.containsKey(CREATE_DEFAULT_BINDINGS))
{
buildBindings = ((Boolean) properties.get(CREATE_DEFAULT_BINDINGS)).booleanValue();
}
if (s11Bindings == null) s11Bindings = new HashSet();
if (s12Bindings == null) s12Bindings = new HashSet();
if (buildBindings)
{
s11Bindings.addAll(getSoap11Transports());
s12Bindings.addAll(getSoap12Transports());
}
createBindings(endpoint, s11Bindings, s12Bindings);
try
{
BindingProvider provider = getBindingProvider();
provider.initialize(endpoint);
endpoint.setBindingProvider(provider);
}
catch (Exception e)
{
if(e instanceof XFireRuntimeException) throw (XFireRuntimeException)e;
throw new XFireRuntimeException("Couldn't load provider.", e);
}
registerHandlers(endpoint);
return endpoint;
}
protected String getTargetNamespace(Class clazz)
{
return NamespaceHelper.makeNamespaceFromClassName(
clazz.getName(), "http");
}
/**
* Get a list of Transports which are enabled over SOAP 1.1.
* @return
*/
public Collection getSoap11Transports()
{
return soap11Transports;
}
public void addSoap11Transport(String id)
{
soap11Transports.add(id);
}
/**
* Get a list of Transports which are enabled over SOAP 1.2.
* @return
*/
public Collection getSoap12Transports()
{
return soap12Transports;
}
public void addSoap12Transport(String id)
{
soap12Transports.add(id);
}
protected void createBindings(Service service, Collection s11, Collection s12)
{
for (Iterator itr = s11.iterator(); itr.hasNext();)
{
String bindingId = (String) itr.next();
Transport t = transportManager.getTransport(bindingId);
if (t instanceof SoapTransport)
{
createSoap11Binding(service, null, bindingId);
}
else if (t == null)
{
throw new XFireRuntimeException("Could not find binding " + bindingId );
}
else
{
throw new XFireRuntimeException("Binding " + bindingId + " is not a SoapTransport!");
}
}
for (Iterator itr = s12.iterator(); itr.hasNext();)
{
String bindingId = (String) itr.next();
Transport t = transportManager.getTransport(bindingId);
if (t instanceof SoapTransport)
{
createSoap12Binding(service, null, bindingId);
}
else if (t == null)
{
throw new XFireRuntimeException("Could not find binding " + bindingId );
}
else
{
throw new XFireRuntimeException("Binding " + bindingId + " is not a SoapTransport!");
}
}
}
/**
* Creates an endpoint for a service. Additionally it opens a channel for this endpoint
* as well.
*
* @param service
* @param name
* @param url
* @param binding
* @return
* @throws Exception
*/
public Endpoint createEndpoint(Service service, QName name, String url, Binding binding)
throws Exception
{
Endpoint endpoint = service.addEndpoint(name, binding, url);
getTransportManager().getTransport(binding.getBindingId()).createChannel(url);
return endpoint;
}
/**
* Create a SOAP 1.2 binding for the specified binding id.
*
* @param service
* @param bindingName The name of the binding. If null, one will be created.
* @param bindingId
* @return
*/
public Soap12Binding createSoap12Binding(Service service, QName bindingName, String bindingId)
{
if (bindingName == null)
{
SoapTransport st = (SoapTransport) transportManager.getTransport(bindingId);
bindingName = new QName(service.getTargetNamespace(),
service.getSimpleName() + st.getName() + "12Binding");
}
Soap12Binding binding = new Soap12Binding(bindingName, bindingId, service);
createSoapBinding(service, binding);
return binding;
}
/**
* Create a SOAP 1.1 binding for the specified binding id.
*
* @param service
* @param bindingName The name of the binding. If null, one will be created.
* @param bindingId
* @return
*/
public Soap11Binding createSoap11Binding(Service service, QName bindingName, String bindingId)
{
if (bindingName == null)
{
SoapTransport st = (SoapTransport) transportManager.getTransport(bindingId);
bindingName = new QName(service.getTargetNamespace(),
service.getSimpleName() + st.getName() + "Binding");
}
Soap11Binding binding = new Soap11Binding(bindingName, bindingId, service);
createSoapBinding(service, binding);
return binding;
}
protected void createSoapBinding(Service service, AbstractSoapBinding binding)
{
ServiceInfo serviceInfo = service.getServiceInfo();
String style = (String) service.getProperty(STYLE);
String use = (String) service.getProperty(USE);
binding.setStyle(style);
binding.setUse(use);
binding.setSerializer(getSerializer(binding));
// Create SOAP metadata for the binding operation
for (Iterator itr = serviceInfo.getOperations().iterator(); itr.hasNext();)
{
OperationInfo op = (OperationInfo) itr.next();
createBindingOperation(service, binding, op);
}
service.addBinding(binding);
getBindingProvider().initialize(service, binding);
}
protected MessageSerializer getSerializer(AbstractSoapBinding binding)
{
return AbstractSoapBinding.getSerializer(binding.getStyle(),
binding.getUse());
}
protected void createBindingOperation(Service service, AbstractSoapBinding binding, OperationInfo op)
{
binding.setSoapAction(op, getAction(op));
createMessageBinding(binding, op);
for (Iterator fitr = op.getFaults().iterator(); fitr.hasNext();)
{
FaultInfo fault = (FaultInfo) fitr.next();
// we don't support fault headers yet...
}
}
private void createMessageBinding(AbstractSoapBinding binding, OperationInfo op)
{
Method method = op.getMethod();
Class[] paramClasses = method.getParameterTypes();
boolean isDoc = binding.getStyle().equals(SoapConstants.STYLE_DOCUMENT);
MessagePartContainer inParts = binding.getHeaders(op.getInputMessage());
MessagePartContainer outParts = null;
if (op.hasOutput()) outParts = binding.getHeaders(op.getOutputMessage());
for (int j = 0; j < paramClasses.length; j++)
{
if (!paramClasses[j].equals(MessageContext.class) && isHeader(method, j))
{
if (isOutParam(method, j))
{
QName q = getOutParameterName(binding.getService(), op, method, j, isDoc);
outParts.addMessagePart(q, paramClasses[j]).setIndex(j);
}
if (isInParam(method, j))
{
QName q = getInParameterName(binding.getService(), op, method, j, isDoc);
inParts.addMessagePart(q, paramClasses[j]).setIndex(j);
}
}
}
Class returnType = method.getReturnType();
if (isHeader(method, -1))
{
if (isOutParam(method, -1))
{
QName q = getOutParameterName(binding.getService(), op, method, -1, isDoc);
outParts.addMessagePart(q, returnType).setIndex(-1);
}
if (isInParam(method, -1))
{
QName q = getInParameterName(binding.getService(), op, method, -1, isDoc);
inParts.addMessagePart(q, returnType).setIndex(-1);
}
}
}
protected void registerHandlers(Service service)
{
service.addInHandler(new ServiceInvocationHandler());
service.addInHandler(new PostInvocationHandler());
service.addOutHandler(new OutMessageSender());
service.addFaultHandler(new FaultSender());
service.addFaultHandler(new CustomFaultHandler());
}
private void setProperties(Service service, Map properties)
{
if (properties == null) return;
for (Iterator itr = properties.entrySet().iterator(); itr.hasNext();)
{
Map.Entry entry = (Map.Entry) itr.next();
service.setProperty((String) entry.getKey(), entry.getValue());
}
}
protected void initializeOperations(Service endpoint, String style)
{
final Method[] methods = endpoint.getServiceInfo().getServiceClass().getMethods();
Arrays.sort(methods, new MethodComparator());
for (int i = 0; i < methods.length; i++)
{
final Method method = methods[i];
if (isValidMethod(method))
{
addOperation(endpoint, method, style);
}
}
}
/**
* Ignore the specified class' declared methods.
* This can be used to not expose certain interfaces as a service.
* By default, the methods specified by the following interfaces/classes are ignored:
* java.lang.Object
* org.omg.CORBA_2_3.portable.ObjectImpl
* org.omg.CORBA.portable.ObjectImpl
* javax.ejb.EJBObject
* javax.ejb.EJBLocalObject
* javax.rmi.CORBA.Stub
*
* @param className the fully qualified class name
*/
public void addIgnoredMethods(String className)
{
ignoredClasses.add(className);
}
protected boolean isValidMethod(final Method method)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.isOperation(method);
if (b != null) return b.booleanValue();
}
return true;
}
protected OperationInfo addOperation(Service endpoint, final Method method, String style)
{
ServiceInfo service = endpoint.getServiceInfo();
final String opName = getOperationName(service, method);
final OperationInfo op = service.addOperation(opName, method);
final Class[] paramClasses = method.getParameterTypes();
boolean isDoc = style.equals(SoapConstants.STYLE_DOCUMENT);
// Setup the input message
MessageInfo inMsg = op.createMessage(createInputMessageName(op));
op.setInputMessage(inMsg);
for (int j = 0; j < paramClasses.length; j++)
{
if (!paramClasses[j].equals(MessageContext.class) &&
!isHeader(method, j) &&
isInParam(method, j))
{
final QName q = getInParameterName(endpoint, op, method, j, isDoc);
MessagePartInfo part = inMsg.addMessagePart(q, paramClasses[j]);
part.setIndex(j);
part.setSchemaElement(isDoc || endpoint.getServiceInfo().isWrapped());
}
}
String mep = getMEP(method);
op.setMEP(mep);
if (hasOutMessage(mep))
{
// Setup the output message
MessageInfo outMsg = op.createMessage(createOutputMessageName(op));
op.setOutputMessage(outMsg);
final Class returnType = method.getReturnType();
if (!returnType.isAssignableFrom(void.class) && !isHeader(method, -1))
{
final QName q = getOutParameterName(endpoint, op, method, -1, isDoc);
MessagePartInfo part = outMsg.addMessagePart(q, method.getReturnType());
part.setIndex(-1);
part.setSchemaElement(isDoc || endpoint.getServiceInfo().isWrapped());
}
for (int j = 0; j < paramClasses.length; j++)
{
if (!paramClasses[j].equals(MessageContext.class) &&
!isHeader(method, j) &&
isOutParam(method, j))
{
final QName q = getInParameterName(endpoint, op, method, j, isDoc);
MessagePartInfo part = outMsg.addMessagePart(q, paramClasses[j]);
part.setIndex(j);
part.setSchemaElement(isDoc || endpoint.getServiceInfo().isWrapped());
}
}
}
if (isCustomFaultsEnabled())
initializeFaults(endpoint, op);
op.setAsync(isAsync(method));
return op;
}
protected boolean isOutParam(Method method, int j)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.isOutParam(method, j);
if (b != null) return b.booleanValue();
}
return true;
}
protected boolean isInParam(Method method, int j)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.isInParam(method, j);
if (b != null) return b.booleanValue();
}
return true;
}
protected QName createInputMessageName(final OperationInfo op)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
QName q = c.getInputMessageName(op);
if (q != null) return q;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected QName createOutputMessageName(final OperationInfo op)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
QName q = c.getOutputMessageName(op);
if (q != null) return q;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected boolean hasOutMessage(String mep)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.hasOutMessage(mep);
if (b != null) return b.booleanValue();
}
return true;
}
protected void initializeFaults(final Service service,
final OperationInfo op)
{
// Set up the fault messages
final Class[] exceptionClasses = op.getMethod().getExceptionTypes();
for (int i = 0; i < exceptionClasses.length; i++)
{
Class exClazz = exceptionClasses[i];
// Ignore XFireFaults because they don't need to be declared
if (exClazz.equals(XFireFault.class) ||
exClazz.equals(Exception.class) ||
exClazz.equals(RuntimeException.class) ||
exClazz.equals(Throwable.class))
{
continue;
}
addFault(service, op, exClazz);
}
}
protected FaultInfo addFault(final Service service, final OperationInfo op, Class exClass)
{
Class beanClass = exClass;
if (isFaultInfoClass(exClass))
{
Method method;
try
{
method = exClass.getMethod("getFaultInfo", new Class[0]);
}
catch (SecurityException e)
{
throw new XFireRuntimeException("Couldn't access getFaultInfo method.", e);
}
catch (NoSuchMethodException e)
{
throw new XFireRuntimeException("Custom faults need a getFaultInfo method.", e);
}
beanClass = method.getReturnType();
}
QName name = getFaultName(service, op, exClass, beanClass);
FaultInfo info = op.addFault(name.getLocalPart());
info.setExceptionClass(exClass);
info.addMessagePart(name, beanClass);
return info;
}
protected boolean isFaultInfoClass(Class exClass)
{
return FaultInfoException.class.isAssignableFrom(exClass);
}
protected QName getFaultName(Service service, OperationInfo o, Class exClass, Class beanClass)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
QName q = c.getFaultName(service, o, exClass, beanClass);
if (q != null) return q;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected String getAction(OperationInfo op)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
String s = c.getAction(op);
if (s != null) return s;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected boolean isHeader(Method method, int j)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.isHeader(method, j);
if (b != null) return b.booleanValue();
}
return true;
}
/**
* Creates a name for the operation from the method name. If an operation with that name
* already exists, a name is create by appending an integer to the end. I.e. if there is already
* two methods named doSomething, the first one will have an operation name of
* "doSomething" and the second "doSomething1".
*
* @param service
* @param method
*/
protected String getOperationName(ServiceInfo service, Method method)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
String s = c.getOperationName(service, method);
if (s != null) return s;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected String getMEP(final Method method)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
String s = c.getMEP(method);
if (s != null) return s;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected boolean isAsync(final Method method)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
Boolean b = c.isAsync(method);
if (b != null) return b.booleanValue();
}
return true;
}
protected QName getInParameterName(final Service service,
final OperationInfo op,
final Method method,
final int paramNumber,
final boolean doc)
{if (paramNumber == -1) throw new RuntimeException();
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
QName q = c.getInParameterName(service, op, method, paramNumber, doc);
if (q != null) return q;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
protected QName getOutParameterName(final Service service,
final OperationInfo op,
final Method method,
final int paramNumber,
final boolean doc)
{
for (Iterator itr = serviceConfigurations.iterator(); itr.hasNext();)
{
ServiceConfiguration c = (ServiceConfiguration) itr.next();
QName q = c.getOutParameterName(service, op, method, paramNumber, doc);
if (q != null) return q;
}
throw new IllegalStateException("ServiceConfiguration must provide a value!");
}
public TransportManager getTransportManager()
{
return transportManager;
}
public void setTransportManager(TransportManager transportManager)
{
this.transportManager = transportManager;
}
public void setBindingProvider(BindingProvider bindingProvider)
{
this.bindingProvider = bindingProvider;
}
public String getStyle()
{
return style;
}
public void setStyle(String style)
{
this.style = style;
}
public String getUse()
{
return use;
}
public void setUse(String use)
{
this.use = use;
}
public boolean isVoidOneWay()
{
return voidOneWay;
}
public void setVoidOneWay(boolean voidOneWay)
{
this.voidOneWay = voidOneWay;
}
public WSDLBuilderFactory getWsdlBuilderFactory()
{
return wsdlBuilderFactory;
}
public void setWsdlBuilderFactory(WSDLBuilderFactory wsdlBuilderFactory)
{
this.wsdlBuilderFactory = wsdlBuilderFactory;
}
public boolean isCustomFaultsEnabled()
{
return customFaultsEnabled;
}
public void setCustomFaultsEnabled(boolean customFaultsEnabled)
{
this.customFaultsEnabled = customFaultsEnabled;
}
public boolean isBindingCreationEnabled()
{
return bindingCreationEnabled;
}
public void setBindingCreationEnabled(boolean bindingCreationEnabled)
{
this.bindingCreationEnabled = bindingCreationEnabled;
}
public Set getIgnoredClasses()
{
return ignoredClasses;
}
public List getServiceConfigurations()
{
return serviceConfigurations;
}
public void setServiceConfigurations(List serviceConfigurations)
{
this.serviceConfigurations = serviceConfigurations;
}
}