All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jvnet.jax_ws_commons.spring.SpringService Maven / Gradle / Ivy
package org.jvnet.jax_ws_commons.spring;
import com.sun.istack.NotNull;
import com.sun.xml.ws.api.BindingID;
import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.pipe.TubelineAssembler;
import com.sun.xml.ws.api.pipe.TubelineAssemblerFactory;
import com.sun.xml.ws.api.server.Container;
import com.sun.xml.ws.api.server.InstanceResolver;
import com.sun.xml.ws.api.server.Invoker;
import com.sun.xml.ws.api.server.SDDocumentSource;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.api.server.Module;
import com.sun.xml.ws.api.server.BoundEndpoint;
import com.sun.xml.ws.binding.BindingImpl;
import com.sun.xml.ws.server.EndpointFactory;
import com.sun.xml.ws.server.ServerRtException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.context.ServletContextAware;
import org.xml.sax.EntityResolver;
import javax.servlet.ServletContext;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingType;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.soap.SOAPBinding;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
/**
* Endpoint. A service object and the infrastructure around it.
*
* @org.apache.xbean.XBean element="service" rootElement="true"
* @author Kohsuke Kawaguchi
*/
// javadoc for this class is used to auto-generate documentation.
public class SpringService implements FactoryBean, ServletContextAware, InitializingBean {
@NotNull
private Class> implType;
// everything else can be null
private Invoker invoker;
private QName serviceName;
private QName portName;
private Container container;
/**
* Source for the service's primary WSDL.
* Set by {@link #afterPropertiesSet()}.
*/
private SDDocumentSource primaryWsdl;
/**
* Resource for the service's primary WSDL.
*
* @see #setPrimaryWsdl(Object)
*/
private Object primaryWSDLResource;
/**
* Sources for the service's metadata.
* Set by {@link #afterPropertiesSet()}.
*/
private Collection extends SDDocumentSource> metadata;
/**
* Resources for the service's metadata.
*
* @see #setMetadata(java.util.Collection)
*/
private Collection metadataResources;
/**
* Entity resolver to use for resolving XML resources.
*
* @see #setResolver(org.xml.sax.EntityResolver)
*/
private EntityResolver resolver;
/**
* Either {@link TubelineAssembler} or {@link TubelineAssemblerFactory}.
*/
private Object assembler;
// binding.
// either everything is null, in which case we default to SOAP 1.1 + features from annotation
// ... or a WSBinding configured externally
private WSBinding binding;
// ... or a BindingID and features
private BindingID bindingID;
private List features;
/**
* Technically speaking, handlers belong to
* {@link WSBinding} and as such it should be configured there,
* but it's just more convenient to let people do so at this object,
* because often people use a stock binding ID constant
* instead of a configured {@link WSBinding} bean.
*/
private List handlers;
private ServletContext servletContext;
/**
* Set automatically by Spring if JAX-WS is used inside web container.
*/
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
///**
// * @org.apache.xbean.Property alias="clazz"
// */
// I wanted to use alias="class", but @class is reserved in Spring, apparently
/**
* Fully qualified class name of the SEI class. Required.
*/
public void setImpl(Class implType) {
this.implType = implType;
}
/**
* Sets the bean that implements the web service methods.
*/
public void setBean(Object sei) {
this.invoker = InstanceResolver.createSingleton(sei).createInvoker();
if(this.implType==null)
// sei could be a AOP proxy, so getClass() is not always reliable.
// so if set explicitly via setImpl, don't override that.
this.implType = sei.getClass();
}
/**
* Sets {@link Invoker} for this endpoint.
* Defaults to {@link InstanceResolver#createDefault(Class) the standard invoker}.
*/
public void setInvoker(Invoker invoker) {
this.invoker = invoker;
}
/**
* Sets the {@link TubelineAssembler} or {@link TubelineAssemblerFactory} instance.
*
* This is an advanced configuration option for those who would like to control
* what processing JAX-WS runtime performs. The default value is {@code null},
* in which case the {@link TubelineAssemblerFactory} is looked up from the META-INF/services .
*/
public void setAssembler(Object assembler) {
if(assembler instanceof TubelineAssembler || assembler instanceof TubelineAssemblerFactory)
this.assembler = assembler;
else
throw new IllegalArgumentException("Invalid type for assembler "+assembler);
}
/**
* Sets the service name of this endpoint.
* Defaults to the name inferred from the impl attribute.
*/
public void setServiceName(QName serviceName) {
this.serviceName = serviceName;
}
/**
* Sets the port name of this endpoint.
* Defaults to the name inferred from the impl attribute.
*/
public void setPortName(QName portName) {
this.portName = portName;
}
/**
* Sets the custom {@link Container}. Optional.
*/
// TODO: how to set the default container?
public void setContainer(Container container) {
this.container = container;
}
/**
* Accepts an externally configured {@link WSBinding}
* for advanced users.
*/
// is there a better way to do this in Spring?
// http://opensource.atlassian.com/projects/spring/browse/SPR-2528?page=all
// says it doesn't support method overloading, so that's out.
public void setBinding(WSBinding binding) {
this.binding = binding;
}
/**
* Sets the binding ID, such as {@value SOAPBinding#SOAP11HTTP_BINDING}
* or {@value SOAPBinding#SOAP12HTTP_BINDING} .
*
*
* If none is specified, {@link BindingType} annotation on SEI is consulted.
* If that fails, {@link SOAPBinding#SOAP11HTTP_BINDING}.
*
* @see SOAPBinding#SOAP11HTTP_BINDING
* @see SOAPBinding#SOAP12HTTP_BINDING
* @see HTTPBinding#HTTP_BINDING
*/
public void setBindingID(String id) {
this.bindingID = BindingID.parse(id);
}
/**
* {@link WebServiceFeature}s that are activated in this endpoint.
*/
public void setFeatures(List features) {
this.features = features;
}
/**
* {@link Handler}s for this endpoint.
* Note that the order is significant.
*
*
* If there's just one handler and that handler is declared elsewhere,
* you can use this as a nested attribute like handlers="#myHandler" .
* Or otherwise a nested <bean> or <ref> tag can be used to
* specify multiple handlers.
*/
public void setHandlers(List handlers) {
this.handlers = handlers;
}
/**
* Optional WSDL for this endpoint.
*
* Defaults to the WSDL discovered in META-INF/wsdl ,
*
* It can be either {@link String}, {@link URL}, or {@link SDDocumentSource}.
*
* If primaryWsdl
is a String
,
* {@link ServletContext} (if available) and {@link ClassLoader}
* are searched for this path, then failing that, it's treated as an
* absolute {@link URL}.
*/
public void setPrimaryWsdl(Object primaryWsdl) throws IOException {
this.primaryWSDLResource = primaryWsdl;
}
/**
* Optional metadata for this endpoint.
*
* The collection can contain {@link String}, {@link URL}, or {@link SDDocumentSource}
* elements.
*
* If element is a String
,
* {@link ServletContext} (if available) and {@link ClassLoader}
* are searched for this path, then failing that, it's treated as an
* absolute {@link URL}.
*/
public void setMetadata(Collection metadata) {
this.metadataResources = metadata;
}
/**
* Sets the {@link EntityResolver} to be used for resolving schemas/WSDLs
* that are referenced. Optional.
*/
public void setResolver(EntityResolver resolver) {
this.resolver = resolver;
}
/**
* Lazily created {@link WSEndpoint} instance.
*/
private WSEndpoint> endpoint;
public WSEndpoint getObject() throws Exception {
if(endpoint==null) {
if(binding==null) {
if(bindingID==null)
bindingID = BindingID.parse(implType);
if(features==null || features.isEmpty())
binding = BindingImpl.create(bindingID);
else
binding = BindingImpl.create(bindingID,
features.toArray(new WebServiceFeature[features.size()]));
} else {
if(bindingID!=null)
throw new IllegalStateException("Both bindingID and binding are configured");
if(features!=null)
throw new IllegalStateException("Both features and binding are configured");
}
// configure handlers. doing this here ensures
// that we are not doing this more than once.
if(handlers!=null) {
List chain = binding.getHandlerChain();
chain.addAll(handlers);
binding.setHandlerChain(chain);
}
if(primaryWsdl==null) {
// attempt to find it on the impl class.
EndpointFactory.verifyImplementorClass(implType);
String wsdlLocation = EndpointFactory.getWsdlLocation(implType);
if (wsdlLocation != null)
primaryWsdl = convertStringToSource(wsdlLocation);
}
endpoint = WSEndpoint.create(implType,false,invoker,serviceName,
portName,new ContainerWrapper(),binding,primaryWsdl,metadata,resolver,true);
}
return endpoint;
}
/**
* Called automatically by Spring after all properties have been set, including
* {@link #servletContext}. This implementation creates
* SDDocumentSource
s from the {@link #primaryWSDLResource} and
* {@link #metadataResources} properties, if provided.
*
* See {@link #setMetadata(java.util.Collection)} and
* {@link #setPrimaryWsdl(Object)} for conversion rules.
*
* @throws Exception if an error occurs while creating
* SDDocumentSource
s from the {@link #primaryWSDLResource} and
* {@link #metadataResources} properties
*
* @see #resolveSDDocumentSource(Object)
*/
public void afterPropertiesSet() throws Exception {
if (this.primaryWSDLResource != null) {
this.primaryWsdl = this.resolveSDDocumentSource(this.primaryWSDLResource);
}
if (this.metadataResources != null) {
List tempList =
new ArrayList(this.metadataResources.size());
for (Object resource : this.metadataResources) {
tempList.add(this.resolveSDDocumentSource(resource));
}
this.metadata = tempList;
}
}
/**
* Resolves a resource ({@link String}, {@link URL}, or {@link SDDocumentSource})
* to a {@link SDDocumentSource}.
*
* See {@link #convertStringToSource(String)} for processing rules relating
* to a String
argument.
*
* @param resource the String
, URL
,
* or SDDocumentSource
to resolve
*
* @return a SDDocumentSource
for the provided resource
*
* @throws IllegalArgumentException if resource
is not an
* instance of String
, URL
, or
* SDDocumentSource
*
* @see #convertStringToSource(String)
* @see SDDocumentSource#create(java.net.URL)
*/
private SDDocumentSource resolveSDDocumentSource(Object resource) {
SDDocumentSource source;
if (resource instanceof String) {
source = this.convertStringToSource((String) resource);
}
else if (resource instanceof URL) {
source = SDDocumentSource.create((URL) resource);
}
else if (resource instanceof SDDocumentSource) {
source = (SDDocumentSource) resource;
}
else {
throw new IllegalArgumentException("Unknown type " + resource);
}
return source;
}
/**
* Converts {@link String} into {@link SDDocumentSource}.
*
* If resourceLocation
is a String
,
* {@link ServletContext} (if available) and {@link ClassLoader}
* are searched for this path, then failing that, it's treated as an
* absolute {@link URL}.
*
* @throws ServerRtException if resourceLocation
cannot be
* resolved through {@link ServletContext} (if available), {@link ClassLoader},
* or as an absolute {@link java.net.URL}.
*/
private SDDocumentSource convertStringToSource(String resourceLocation) {
URL url = null;
if (servletContext != null) {
// in the servlet environment, consult ServletContext so that we can load
// WEB-INF/wsdl/... and so on.
try {
url = servletContext.getResource(resourceLocation);
} catch (MalformedURLException e) {
// ignore it and try the next method
}
}
if (url == null) {
// also check a resource in classloader.
ClassLoader cl = implType.getClassLoader();
url = cl.getResource(resourceLocation);
}
if (url == null) {
try {
url = new URL(resourceLocation);
} catch (MalformedURLException e) {
// ignore it throw exception later
}
}
if (url == null) {
throw new ServerRtException("cannot.load.wsdl", resourceLocation);
}
return SDDocumentSource.create(url);
}
public boolean isSingleton() {
return true;
}
public Class getObjectType() {
return WSEndpoint.class;
}
private class ContainerWrapper extends Container {
public T getSPI(Class spiType) {
// allow specified TubelineAssembler to be used
if(spiType==TubelineAssemblerFactory.class) {
if(assembler instanceof TubelineAssemblerFactory)
return spiType.cast(assembler);
if(assembler instanceof TubelineAssembler) {
return spiType.cast(new TubelineAssemblerFactory() {
public TubelineAssembler doCreate(BindingID bindingId) {
return (TubelineAssembler)assembler;
}
});
}
}
if(container!=null) {
// delegate to the specified container
T t = container.getSPI(spiType);
if(t!=null)
return t;
}
if(spiType==Module.class) {
// fall back default implementation
return spiType.cast(module);
}
return null;
}
private final Module module = new Module() {
private final List endpoints = new ArrayList();
public @NotNull List getBoundEndpoints() {
return endpoints;
}
};
}
}