All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.webcohesion.enunciate.modules.jaxws.model.EndpointInterface Maven / Gradle / Ivy

There is a newer version: 2.18.1
Show newest version
/**
 * 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 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 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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy