com.webcohesion.enunciate.modules.jaxws.model.EndpointInterface Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of enunciate-jaxws Show documentation
Show all versions of enunciate-jaxws Show documentation
Model processing for JAX-WS API.
/**
* Copyright © 2006-2016 Web Cohesion ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.webcohesion.enunciate.modules.jaxws.model;
import com.webcohesion.enunciate.EnunciateException;
import com.webcohesion.enunciate.facets.Facet;
import com.webcohesion.enunciate.facets.HasFacets;
import com.webcohesion.enunciate.javac.TypeElementComparator;
import com.webcohesion.enunciate.javac.decorations.element.DecoratedTypeElement;
import com.webcohesion.enunciate.metadata.ClientName;
import com.webcohesion.enunciate.metadata.soap.SoapBindingName;
import com.webcohesion.enunciate.modules.jaxws.EnunciateJaxwsContext;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import java.util.*;
/**
* A type or interface specified as a web service endpoint interface. This decorator can only be applied to either interfaces or classes
* that implicitly define an endpoint interface (see spec, section 3.3).
*
* @author Ryan Heaton
*/
public class EndpointInterface extends DecoratedTypeElement implements HasFacets {
private final javax.jws.WebService annotation;
private final List webMethods;
private final Collection impls;
private final Map metaData = new HashMap();
private final Set facets = new TreeSet();
private final boolean aggressiveWebMethodExcludePolicy;
private final EnunciateJaxwsContext context;
/**
* Construct an endoint interface.
*
* @param delegate The delegate.
* @param implementationCandidates The type declarations to be considered as implementation candidates (the ones that can't be seen by APT.)
*/
public EndpointInterface(TypeElement delegate, Set extends Element> implementationCandidates, EnunciateJaxwsContext context) {
this(delegate, implementationCandidates, false, context);
}
/**
* Construct an endoint interface.
*
* @param delegate The delegate.
* @param implementationCandidates The type declarations to be considered as implementation candidates (the ones that can't be seen by APT.)
* @param aggressiveWebMethodExcludePolicy Whether an aggressive policy for excluding web methods should be used. See https://jira.codehaus.org/browse/ENUNCIATE-796.
*/
public EndpointInterface(TypeElement delegate, Set extends Element> implementationCandidates, boolean aggressiveWebMethodExcludePolicy, EnunciateJaxwsContext context) {
super(delegate, context.getContext().getProcessingEnvironment());
this.context = context;
this.aggressiveWebMethodExcludePolicy = aggressiveWebMethodExcludePolicy;
this.facets.addAll(Facet.gatherFacets(delegate, context.getContext()));
annotation = getAnnotation(javax.jws.WebService.class);
impls = new ArrayList();
if (annotation != null) {
if (isClass()) {
//if the declaration is a class, the endpoint interface is implied...
impls.add(new EndpointImplementation(getDelegate(), this, context));
}
else {
Set potentialImpls = new TreeSet(new TypeElementComparator());
potentialImpls.addAll(ElementFilter.typesIn(context.getContext().getApiElements()));
if (implementationCandidates != null) {
potentialImpls.addAll(ElementFilter.typesIn(implementationCandidates));
}
for (TypeElement declaration : potentialImpls) {
if (isEndpointImplementation(declaration)) {
WebService ws = declaration.getAnnotation(WebService.class);
if (getQualifiedName().toString().equals(ws.endpointInterface())) {
impls.add(new EndpointImplementation(declaration, this, context));
}
}
}
}
}
List webMethods = new ArrayList();
for (ExecutableElement method : getMethods()) {
if (isWebMethod(method)) {
webMethods.add(new WebMethod(method, this, context));
}
}
if (delegate.getKind() == ElementKind.CLASS) {
//the spec says we need to consider superclass methods, too...
TypeMirror superclass = delegate.getSuperclass();
if (superclass instanceof DeclaredType) {
Element declaration = ((DeclaredType) superclass).asElement();
if (declaration instanceof TypeElement) {
while ((declaration != null) && (!Object.class.getName().equals(((TypeElement)declaration).getQualifiedName().toString()))) {
for (ExecutableElement method : ElementFilter.methodsIn(declaration.getEnclosedElements())) {
if (isWebMethod(method)) {
//todo: if this method is overridden, don't add it.
webMethods.add(new WebMethod(method, this, context));
}
}
superclass = ((TypeElement)declaration).getSuperclass();
if (superclass == null || superclass.getKind() == TypeKind.NONE) {
declaration = null;
}
else {
declaration = ((DeclaredType) superclass).asElement();
}
}
}
}
}
this.webMethods = webMethods;
}
public EnunciateJaxwsContext getContext() {
return context;
}
/**
* The name of this web service.
*
* @return The name of this web service.
*/
public String getPortTypeName() {
String name = null;
if (annotation != null) {
name = annotation.name();
}
if ((name == null) || ("".equals(name))) {
name = getSimpleName().toString();
}
return name;
}
/**
* The service name of this web service.
*
* @return The service name of this web service.
*/
public String getServiceName() {
String serviceName = null;
if (annotation != null) {
serviceName = annotation.serviceName();
}
if (((serviceName == null) || ("".equals(serviceName))) && getEndpointImplementations().size() == 1) {
WebService implAnnotation = getEndpointImplementations().iterator().next().getAnnotation(WebService.class);
if (implAnnotation != null) {
serviceName = implAnnotation.serviceName();
}
}
if ((serviceName == null) || ("".equals(serviceName))) {
serviceName = getSimpleName() + "Service";
}
return serviceName;
}
/**
* The path where this service is mounted.
*
* @return The path where this service is mounted.
*/
public String getPath() {
for (EndpointImplementation implementation : getEndpointImplementations()) {
String path = implementation.getPath();
if (path != null) {
return path;
}
}
return "/" + getServiceName();
}
/**
* Gets the target namespace of this web service.
*
* @return the target namespace of this web service.
*/
public String getTargetNamespace() {
String targetNamespace = null;
if (annotation != null) {
targetNamespace = annotation.targetNamespace();
}
if ((targetNamespace == null) || ("".equals(targetNamespace))) {
targetNamespace = calculateNamespaceURI();
}
return targetNamespace;
}
/**
* The simple name for client-side code generation.
*
* @return The simple name for client-side code generation.
*/
public String getClientSimpleName() {
String clientSimpleName = getSimpleName().toString();
ClientName clientName = getAnnotation(ClientName.class);
if (clientName != null) {
clientSimpleName = clientName.value();
}
return clientSimpleName;
}
/**
* Calculates a namespace URI for a given package. Default implementation uses the algorithm defined in
* section 3.2 of the jax-ws spec.
*
* @return The calculated namespace uri.
*/
protected String calculateNamespaceURI() {
PackageElement pkg = getPackage();
if ((pkg == null) || ("".equals(pkg.getQualifiedName().toString()))) {
throw new EnunciateException(getQualifiedName() + ": a web service in no package must specify a target namespace.");
}
String[] tokens = pkg.getQualifiedName().toString().split("\\.");
String uri = "http://";
for (int i = tokens.length - 1; i >= 0; i--) {
uri += tokens[i];
if (i != 0) {
uri += ".";
}
}
uri += "/";
return uri;
}
/**
* The set of namespace URIs that this web service references.
*
* @return The set of namespace URIs that this web service references.
*/
public Set getReferencedNamespaces() {
HashSet namespaces = new HashSet();
namespaces.add(getTargetNamespace());
Collection webMethods = getWebMethods();
for (WebMethod webMethod : webMethods) {
namespaces.addAll(webMethod.getReferencedNamespaces());
}
return namespaces;
}
/**
* Get the web methods for this web service.
*
* @return the web methods for this web service.
*/
public List getWebMethods() {
return this.webMethods;
}
/**
* A quick check to see if a method is a web method.
*/
public boolean isWebMethod(ExecutableElement method) {
boolean isWebMethod = method.getModifiers().contains(Modifier.PUBLIC);
javax.jws.WebMethod annotation = method.getAnnotation(javax.jws.WebMethod.class);
if (annotation != null) {
isWebMethod &= !annotation.exclude();
}
else if (this.aggressiveWebMethodExcludePolicy) {
isWebMethod = false;
}
return isWebMethod;
}
/**
* Finds the endpoint implemenations of this interface.
*
* @return The endpoint implementations of this interface.
*/
public Collection getEndpointImplementations() {
return this.impls;
}
/**
* A quick check to see if a declaration is an endpoint implementation.
*/
protected boolean isEndpointImplementation(TypeElement declaration) {
if (declaration.getKind() == ElementKind.CLASS && !declaration.getQualifiedName().equals(getQualifiedName())) {
WebService webServiceInfo = declaration.getAnnotation(WebService.class);
return webServiceInfo != null && getQualifiedName().toString().equals(webServiceInfo.endpointInterface());
}
return false;
}
/**
* The SOAP binding style specified on this endpoint interface.
*
* Note: the specification is unclear on how to deal with the specific binding annotations of the
* associated endpoint implementation classes. It is a assumed that the annotations of the endpoint
* implementation classes override the annotations on the endpoint interface.
*
* @return The SOAP binding style specified on this endpoint interface.
*/
public SOAPBinding.Style getSoapBindingStyle() {
SOAPBinding.Style style = SOAPBinding.Style.DOCUMENT;
SOAPBinding bindingInfo = getAnnotation(SOAPBinding.class);
if (bindingInfo != null) {
style = bindingInfo.style();
}
return style;
}
public Collection getBindingTypes() {
ArrayList bindingTypes = new ArrayList();
for (EndpointImplementation implementation : getEndpointImplementations()) {
bindingTypes.add(implementation.getBindingType());
}
if (bindingTypes.isEmpty()) {
//spec says if no bindings are present, use SOAP 1.1
bindingTypes.add(BindingType.SOAP_1_1);
}
return bindingTypes;
}
/**
* The name of the soap binding. This is just used in the WSDL, so it's not really necessary-- it's more for aesthetic purposes.
*
* @return The name of the soap binding.
* @see com.webcohesion.enunciate.metadata.soap.SoapBindingName
*/
public String getSoapBindingName() {
String name = getSimpleName() + "PortBinding";
SoapBindingName bindingNameInfo = getAnnotation(SoapBindingName.class);
if (bindingNameInfo != null) {
name = bindingNameInfo.value();
}
return name;
}
/**
* The SOAP binding use of this web method.
*
* @return The SOAP binding use of this web method.
*/
public SOAPBinding.Use getSoapUse() {
SOAPBinding.Use use = SOAPBinding.Use.LITERAL;
SOAPBinding bindingInfo = getAnnotation(SOAPBinding.class);
if (bindingInfo != null) {
use = bindingInfo.use();
}
return use;
}
/**
* The SOAP parameter style of this web method.
*
* @return The SOAP parameter style of this web method.
*/
public SOAPBinding.ParameterStyle getSoapParameterStyle() {
SOAPBinding.ParameterStyle style = SOAPBinding.ParameterStyle.WRAPPED;
SOAPBinding bindingInfo = getAnnotation(SOAPBinding.class);
if (bindingInfo != null) {
style = bindingInfo.parameterStyle();
}
return style;
}
/**
* The metadata associated with this endpoint interface.
*
* @return The metadata associated with this endpoint interface.
*/
public Map getMetaData() {
return Collections.unmodifiableMap(this.metaData);
}
/**
* Set the metadata associated with this endpoint interface.
*
* @param name The name of the metadata.
* @param data The data.
*/
public void putMetaData(String name, Object data) {
this.metaData.put(name, data);
}
/**
* The facets here applicable.
*
* @return The facets here applicable.
*/
public Set getFacets() {
return facets;
}
}