Package org.apache.axis2.jaxws.description.impl

Source Code of org.apache.axis2.jaxws.description.impl.EndpointDescriptionImpl

/*
* Copyright 2004,2005 The Apache Software Foundation.
* Copyright 2006 International Business Machines Corp.
*
* 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 org.apache.axis2.jaxws.description.impl;

import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import javax.jws.WebService;
import javax.wsdl.Binding;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.http.HTTPBinding;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingType;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.soap.SOAPBinding;

import org.apache.axis2.AxisFault;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.OutInAxisOperation;
import org.apache.axis2.description.OutOnlyAxisOperation;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.WSDL11ToAllAxisServicesBuilder;
import org.apache.axis2.description.WSDL11ToAxisServiceBuilder;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.EndpointDescriptionJava;
import org.apache.axis2.jaxws.description.EndpointDescriptionWSDL;
import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.description.ServiceDescriptionWSDL;
import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
import org.apache.axis2.jaxws.description.builder.MDQConstants;
import org.apache.axis2.jaxws.description.builder.WsdlComposite;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.util.WSDL4JWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* @see ../EndpointDescription
*
*/
/*
* TODO: EndpointDescription should be created via AxisService objects and not directly from WSDL
* IMPORTANT NOTE: Axis2 currently only supports 1 service and 1 port under that service.  When that is
* fixed, that will probably have an impact on this class.  In particular, I think this should be created
* somehow from an AxisService/AxisPort combination, and not directly from the WSDL.
*/
class EndpointDescriptionImpl implements EndpointDescription, EndpointDescriptionJava, EndpointDescriptionWSDL {
   
    private ServiceDescriptionImpl parentServiceDescription;
    private AxisService axisService;

    private QName portQName;
    private QName serviceQName;

    // Corresponds to a port that was added dynamically via addPort and is not declared (either in WSDL or annotations)
    private boolean isDynamicPort;
   
    // If the WSDL is fully specified, we could build the AxisService from the WSDL
    private boolean isAxisServiceBuiltFromWSDL;
   
    private String serviceImplName;  //class name of the service impl or SEI
   
    // Note that an EndpointInterfaceDescription will ONLY be set for an Endpoint-based implementation;
    // it will NOT be set for a Provider-based implementation
    private EndpointInterfaceDescription endpointInterfaceDescription;

    // This can be an SEI (on the client or server) or a Service implentation (server only)
    // Note that for clients that are Dispatch, this will be null.  Also note that a client that was initially
    // dispatch (sei = null) could later do a getPort(sei), at which time the original EndpointDescription will be
    // updated with the SEI information.
    private Class implOrSEIClass;

    //On Client side, there should be One ServiceClient instance per AxisSerivce
    private ServiceClient serviceClient = null;
   
    //This is the base WebService or WebServiceProvider that we are processing
    DescriptionBuilderComposite composite = null;
    // Set of packages that are needed to marshal/unmashal data (used to set JAXBContext)
    TreeSet<String> packages = null;
   
    // The JAX-WS Handler port information corresponding to this endpoint
    private PortInfo portInfo;
   
    private String clientBindingID;
    // The effective endpoint address.  It could be set by the client or come from the WSDL SOAP address
    private String endpointAddress;
    // The endpoint address from the WSDL soap:address extensibility element if present.
    private String wsdlSOAPAddress;
   
    private static final Log log = LogFactory.getLog(EndpointDescriptionImpl.class);

   
    // ===========================================
    // ANNOTATION related information
    // ===========================================
   
    // ANNOTATION: @WebService and @WebServiceProvider
    // Only one of these two annotations will be set; they are mutually exclusive
    private WebService          webServiceAnnotation;
    private WebServiceProvider  webServiceProviderAnnotation;

    // Information common to both WebService and WebServiceProvider annotations
    private String              annotation_WsdlLocation;
    private String              annotation_ServiceName;
    private String              annotation_PortName;
    private String              annotation_TargetNamespace;
    // Information only set on WebService annotation
    // ANNOTATION: @WebService
    private String              webService_EndpointInterface;
    private String              webService_Name;

    // ANNOTATION: @ServiceMode
    // Note this is only valid on a Provider-based endpoint
    private ServiceMode         serviceModeAnnotation;
    private Service.Mode        serviceModeValue;
    // Default ServiceMode.value per JAXWS Spec 7.1 "javax.xml.ServiceMode" pg 79
    public static final javax.xml.ws.Service.Mode  ServiceMode_DEFAULT = javax.xml.ws.Service.Mode.PAYLOAD;
   
    // ANNOTATION: @BindingType
    private BindingType         bindingTypeAnnotation;
    private String              bindingTypeValue;
    // Default BindingType.value per JAXWS Spec Sec 7.8 "javax.xml.ws.BindingType" pg 83
    // and Sec 1.4 "SOAP Transport and Transfer Bindings" pg 119
    public static final String  BindingType_DEFAULT = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
   
    // ANNOTATION: @HandlerChain
    // TODO: @HandlerChain support
    // TODO: This needs to be a collection of handler descriptions; use JAX-WS Appendix B Handler Chain Configuration File Schema as a starting point
    private ArrayList<String> handlerList = new ArrayList<String>();

    /**
     * Create an EndpointDescription based on the WSDL port.  Note that per the JAX-WS Spec (Final Release, 4/19/2006
     * Section 4.2.3 Proxies, page 55)the "namespace component of the port is the target namespace of the WSDL
     * definition document".
     * Note this is currently only used on the client-side (this may change).
     *
     * @param theClass The SEI or Impl class.  This will be NULL for Dispatch clients
     *                 since they don't use an SEI
     */
    EndpointDescriptionImpl(Class theClass, QName portName, ServiceDescriptionImpl parent) {
        this(theClass, portName, false, parent);
    }
    EndpointDescriptionImpl(Class theClass, QName portName, boolean dynamicPort, ServiceDescriptionImpl parent) {
        // TODO: This and the other constructor will (eventually) take the same args, so the logic needs to be combined
        // TODO: If there is WSDL, could compare the namespace of the defn against the portQName.namespace
        this.parentServiceDescription = parent;
        this.implOrSEIClass = theClass;
        // REVIEW: setting these should probably be done in the getters!  It needs to be done before we try to select a
        //         port to use if one wasn't specified because we'll try to get to the annotations to get the PortType
        if (this.implOrSEIClass != null) {
            webServiceAnnotation = (WebService) implOrSEIClass.getAnnotation(WebService.class);
            webServiceProviderAnnotation = (WebServiceProvider) implOrSEIClass.getAnnotation(WebServiceProvider.class);
        }
        this.isDynamicPort = dynamicPort;
        if (DescriptionUtils.isEmpty(portName)) {
            // If the port name is null, then per JAX-WS 2.0 spec p. 55, the runtime is responsible for selecting the port.
            this.portQName = selectPortToUse();
        }
        else {
            this.portQName = portName;
        }
        // At this point, there must be a port QName set, either as passed in, or determined from the WSDL and/or annotations.
        // If not, that is an error.
        if (this.portQName == null) {
            if (log.isDebugEnabled()) {
                log.debug("PortQName was null and could not be determined by runtime.  Class: " + theClass + "; ServiceDescription: " + parent);
            }
            throw ExceptionFactory.makeWebServiceException("EndpointDescription: portQName could not be determined for class " + theClass);
        }
       
        // TODO: Refactor this with the consideration of no WSDL/Generic Service/Annotated SEI
        setupAxisService();
        addToAxisService();

        buildDescriptionHierachy();
        addAnonymousAxisOperations();
        // This will set the serviceClient field after adding the AxisService to the AxisConfig
        getServiceClient();
        // Give the configuration builder a chance to finalize configuration for this service
        try {
            getServiceDescriptionImpl().getClientConfigurationFactory().completeAxis2Configuration(axisService);
        } catch (DeploymentException e) {
            // TODO RAS & NLS
            if (log.isDebugEnabled()) {
                log.debug("Caught DeploymentException attempting to complete configuration on AxisService: "
                        + axisService + " for ServiceDesription: " + parent, e);
            }
            throw ExceptionFactory.makeWebServiceException("Unable to complete configuration due to exception " + e, e);
        } catch (Exception e) {
            // TODO RAS & NLS
            if (log.isDebugEnabled()) {
                log.debug("Caught Exception attempting to complete configuration on AxisService: "
                        + axisService + " for ServiceDesription: " + parent, e);
            }
            throw ExceptionFactory.makeWebServiceException("Unable to complete configuration due to exception " + e, e);
        }
    }
   
    /**
     * Create an EndpointDescription based on the DescriptionBuilderComposite. 
     * Note that per the JAX-WS Spec (Final Release, 4/19/2006
     * Section 4.2.3 Proxies, page 55)the "namespace component of the port is the target namespace of the WSDL
     * definition document".
     *
     * @param theClass The SEI or Impl class.  This will be NULL for Dispatch clients
     *                 since they don't use an SEI
     */
    EndpointDescriptionImpl(ServiceDescriptionImpl parent, String serviceImplName) {
     
      // TODO: This and the other constructor will (eventually) take the same args, so the logic needs to be combined
        // TODO: If there is WSDL, could compare the namespace of the defn against the portQName.namespace
        this.parentServiceDescription = parent;
        this.serviceImplName = serviceImplName;
        this.implOrSEIClass = null;

     composite = getServiceDescriptionImpl().getDescriptionBuilderComposite();
    if (composite == null){
            throw ExceptionFactory.makeWebServiceException("EndpointDescription.EndpointDescription: parents DBC is null");
    }

        //Set the base level of annotation that we are processing...currently
        // a 'WebService' or a 'WebServiceProvider'
        if (composite.getWebServiceAnnot() != null)
          webServiceAnnotation = composite.getWebServiceAnnot();
        else
          webServiceProviderAnnotation = composite.getWebServiceProviderAnnot();
       
        // REVIEW: Maybe this should be an error if the name has already been set and it doesn't match
        // Note that on the client side, the service QN should be set; on the server side it will not be.
        if (DescriptionUtils.isEmpty(getServiceDescription().getServiceQName())) {
            getServiceDescriptionImpl().setServiceQName(getServiceQName());
        }
        //Call the getter to insure the qualified port name is set.
        getPortQName();
   
        // TODO: Refactor this with the consideration of no WSDL/Generic Service/Annotated SEI
        setupAxisServiceFromDBL();
        addToAxisService()//Add a reference to this EndpointDescription to the AxisService

        //TODO: Need to remove operations from AxisService that have 'exclude = true
        //      then call 'validateOperations' to verify that WSDL and AxisService match up,
        //      Remember that this will only happen when we generate an AxisService from existing
        //    WSDL and then need to perform further processing because we have annotations as well
        //    If there is no WSDL, we would never process the Method to begin with.
       
        buildDescriptionHierachy();
       
      WsdlComposite wsdlComposite = null;
       
      //Determine if we need to generate WSDL
      //Assumption is that WSDL will be generated only when the composite does not contain a
      //Wsdl Definition
      if (
        (isEndpointBased() && DescriptionUtils.isEmpty(getAnnoWebServiceEndpointInterface()))
             ||
        (!isEndpointBased())
      ) {
        //This is either an implicit SEI, or a WebService Provider

        wsdlComposite = generateWSDL(composite);
       
      } else if (isEndpointBased()) {
        //This impl class specifies an SEI...this is a special case. There is a bug
        //in the tooling that allows for the wsdllocation to be specifed on either the
        //impl. class, or the SEI, or both. So, we need to look for the wsdl as follows:
        //      1. If the Wsdl exists on the SEI, then check for it on the impl.
        //      2. If it is not found in either location, in that order, then generate
     
      DescriptionBuilderComposite seic =
          getServiceDescriptionImpl().getDBCMap().get(composite.getWebServiceAnnot().endpointInterface());
 
     
      //Only generate WSDL if a definition doesn't already exist
      if (seic.getWsdlDefinition() == null
        wsdlComposite = generateWSDL(composite)
      }
     
        //Store the WsdlComposite only if it was created
      if (wsdlComposite != null) {
            Parameter wsdlCompositeParameter = new Parameter();
            wsdlCompositeParameter.setName(MDQConstants.WSDL_COMPOSITE);
            wsdlCompositeParameter.setValue(wsdlComposite);
           
            try {
              axisService.addParameter(wsdlCompositeParameter);
            } catch (Exception e) {
              throw ExceptionFactory.makeWebServiceException("EndpointDescription: Unable to add wsdlComposite parm. to AxisService");
            }     
      }
               
        //Save the WSDL Location and the WsdlDefinition, value depends on whether wsdl was generated
        Parameter wsdlLocationParameter = new Parameter();
        wsdlLocationParameter.setName(MDQConstants.WSDL_LOCATION);
        Parameter wsdlDefParameter = new Parameter();
        wsdlDefParameter.setName(MDQConstants.WSDL_DEFINITION);   
      
        if (wsdlComposite != null) {
         
          wsdlLocationParameter.setValue(wsdlComposite.getWsdlFileName());
        wsdlDefParameter.setValue(getServiceDescriptionImpl().getGeneratedWsdlWrapper().getDefinition());
        } else {

          wsdlLocationParameter.setValue(getAnnoWebServiceWSDLLocation());
            wsdlDefParameter.setValue(getServiceDescriptionImpl().getWSDLWrapper().getDefinition());
        }
         
        try {
          axisService.addParameter(wsdlDefParameter);
          axisService.addParameter(wsdlLocationParameter);                       
        } catch (Exception e) {
          throw ExceptionFactory.makeWebServiceException("EndpointDescription: Unable to add parms. to AxisService");
        }  
    }
   
    /**
     * Create from an annotated implementation or SEI class.
     * Note this is currently used only on the server-side (this probably won't change).
     *
     * @param theClass An implemntation or SEI class
     * @param portName May be null; if so the annotation is used
     * @param parent
     */
    EndpointDescriptionImpl(Class theClass, QName portName, AxisService axisService, ServiceDescriptionImpl parent) {
        this.parentServiceDescription = parent;
        this.portQName = portName;
        this.implOrSEIClass = theClass;
        this.axisService = axisService;
       
        addToAxisService();

        buildEndpointDescriptionFromAnnotations();
       
        // The anonymous AxisOperations are currently NOT added here.  The reason
        // is that (for now) this is a SERVER-SIDE code path, and the anonymous operations
        // are only needed on the client side.
    }

    private void addToAxisService() {
        // Add a reference to this EndpointDescription object to the AxisService
        if (axisService != null) {
            Parameter parameter = new Parameter();
            parameter.setName(EndpointDescription.AXIS_SERVICE_PARAMETER);
            parameter.setValue(this);
            // TODO: What to do if AxisFault
            try {
                axisService.addParameter(parameter);
            } catch (AxisFault e) {
                // TODO: Throwing wrong exception
                e.printStackTrace();
                throw new UnsupportedOperationException("Can't add AxisService param: " + e);
            }
        }
    }

    private void buildEndpointDescriptionFromAnnotations() {
        // TODO: The comments below are not quite correct; this method is used on BOTH the
        //       client and server.  On the client the class is always an SEI.  On the server it
      //     is always a service impl which may be a provider or endpoint based;
      //     endpoint based may reference an SEI class
       
        // The Service Implementation class could be either Provider-based or Endpoint-based.  The
        // annotations that are present are similar but different.  Conformance requirements
        // per JAX-WS
        // - A Provider based implementation MUST carry the @WebServiceProvider annotation
        //   per section 5.1 javax.xml.ws.Provider on page 63
        // - An Endpoint based implementation MUST carry the @WebService annotation per JSR-181
        //   (reference TBD) and JAX-WS (reference TBD)
        // - An Endpoint based implementation @WebService annotation MAY reference an endpoint
        //   interface
        // - The @WebService and @WebServiceProvider annotations can not appear in the same class per
        //   JAX-WS section 7.7 on page 82.

        // Verify that one (and only one) of the required annotations is present.
        // TODO: Add tests to verify this error checking
     
      if (!getServiceDescriptionImpl().isDBCMap()) {
       
        webServiceAnnotation = (WebService) implOrSEIClass.getAnnotation(WebService.class);
        webServiceProviderAnnotation = (WebServiceProvider) implOrSEIClass.getAnnotation(WebServiceProvider.class);
           
        if (webServiceAnnotation == null && webServiceProviderAnnotation == null)
          // TODO: NLS
          throw ExceptionFactory.makeWebServiceException("Either WebService or WebServiceProvider annotation must be present on " + implOrSEIClass);
        else if (webServiceAnnotation != null && webServiceProviderAnnotation != null)
          // TODO: NLS
          throw ExceptionFactory.makeWebServiceException("Both WebService or WebServiceProvider annotations cannot be presenton " + implOrSEIClass);
      }
        // If portName was specified, set it.  Otherwise, we will get it from the appropriate
        // annotation when the getter is called.
        // TODO: If the portName is specified, should we verify it against the annotation?
        // TODO: Add tests: null portName, !null portName, portName != annotation value
        // TODO: Get portName from annotation if it is null.

        // If this is an Endpoint-based service implementation (i.e. not a
        // Provider-based one), then create the EndpointInterfaceDescription to contain
        // the operations on the endpoint.  Provider-based endpoints don't have operations
        // associated with them, so they don't have an EndpointInterfaceDescription.
      if (webServiceAnnotation != null) {
        // If this impl class references an SEI, then use that SEI to create the EndpointInterfaceDesc.
        // TODO: Add support for service impl endpoints that don't reference an SEI; remember
        //       that this is also called with just an SEI interface from svcDesc.updateWithSEI()
        String seiClassName = getAnnoWebServiceEndpointInterface();
       
        if (!getServiceDescriptionImpl().isDBCMap()){
          Class seiClass = null;
          if (DescriptionUtils.isEmpty(seiClassName)) {
            // For now, just build the EndpointInterfaceDesc based on the class itself.
            // TODO: The EID ctor doesn't correctly handle anything but an SEI at this
            //       point; e.g. it doesn't publish the correct methods of just an impl.
            seiClass = implOrSEIClass;
          }
          else {
            try {
              // TODO: Using Class forName() is probably not the best long-term way to get the SEI class from the annotation
              seiClass = forName(seiClassName, false,
                                getContextClassLoader());
              // Catch Throwable as ClassLoader can throw an NoClassDefFoundError that
              // does not extend Exception, so lets catch everything that extends Throwable
                    // rather than just Exception.
            } catch (Throwable e) {
              // TODO: Throwing wrong exception
              e.printStackTrace();
              throw new UnsupportedOperationException("Can't create SEI class: " + e);
            }
          }
          endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(seiClass, this);
        } else {
          //TODO: Determine if we need logic here to determine implied SEI or not. This logic
          //    may be handled by EndpointInterfaceDescription
         
          if (DescriptionUtils.isEmpty(getAnnoWebServiceEndpointInterface())) {
                     
            //TODO: Build the EndpointInterfaceDesc based on the class itself
            endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(composite, true, this);
           
          } else {
            //Otherwise, build the EID based on the SEI composite
            endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(
                  getServiceDescriptionImpl().getDBCMap().get(seiClassName),
                  false,
                  this);
          }
        }
      } else {
        //TODO: process a WebServiceProvider
      }
    }
   
    public QName getPortQName() {
        // REVIEW: Implement WSDL/Annotation merge? May be OK as is; not sure how would know WHICH port Qname to get out of the WSDL if
        //       we didn't use annotations.
        if (portQName == null) {
            // The name was not set by the constructors, so get it from the
            // appropriate annotation.
            String name = getAnnoWebServicePortName();
            String tns = getAnnoWebServiceTargetNamespace();
           
            // TODO: Check for name &/| tns null or empty string and add tests for same
            portQName = new QName(tns, name);
        }
        return portQName;
    }
   
    public QName getServiceQName() {
        if (serviceQName == null) {
            // If the service name has been set on the Service, use that.  Otherwise
            // get the name off the annotations
            QName serviceDescQName = getServiceDescription().getServiceQName();
            if (!DescriptionUtils.isEmpty(serviceDescQName)) {
                serviceQName = serviceDescQName;
            }
            else {
                String localPart = getAnnoWebServiceServiceName();
                String tns = getAnnoWebServiceTargetNamespace();
                serviceQName = new QName(tns, localPart);
            }
        }
        return serviceQName;
    }
   
    public ServiceDescription getServiceDescription() {
        return parentServiceDescription;
    }
   
    ServiceDescriptionImpl getServiceDescriptionImpl() {
        return (ServiceDescriptionImpl) parentServiceDescription;
    }
   
    public EndpointInterfaceDescription getEndpointInterfaceDescription() {
        return endpointInterfaceDescription;
    }

    public AxisService getAxisService() {
        return axisService;
    }
   
    boolean isDynamicPort() {
        return isDynamicPort;
    }
   
    void updateWithSEI(Class sei) {
        // Updating with an SEI is only valid for declared ports; it is not valid for dynamic ports.
        if (isDynamicPort()) {
            // TODO: RAS and NLS
            throw ExceptionFactory.makeWebServiceException("Can not update an SEI on a dynamic port.  PortQName:" + portQName);
        }
        if (sei == null) {
            // TODO: RAS and NLS
            throw ExceptionFactory.makeWebServiceException("EndpointDescription.updateWithSEI was passed a null SEI.  PortQName:" + portQName);
        }

        if (endpointInterfaceDescription != null) {
            // The EndpointInterfaceDescription was created previously based on the port declaration (i.e. WSDL)
            // so update that with information from the SEI annotations
            ((EndpointInterfaceDescriptionImpl) endpointInterfaceDescription).updateWithSEI(sei);
        }
        else {
            // An EndpointInterfaceDescription does not exist yet.  This currently happens in the case where there is
            // NO WSDL provided and a Dispatch client is created for prior to a getPort being done for that port.
            // There was no WSDL to create the EndpointInterfaceDescription from and there was no annotated SEI to
            // use at that time.  Now we have an annotated SEI, so create the EndpointInterfaceDescription now.
            endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(sei, this);
        }
        return;
    }
    private void setupAxisService() {
        // TODO: Need to use MetaDataQuery validator to merge WSDL (if any) and annotations (if any)
        // Build up the AxisService.  Note that if this is a dynamic port, then we don't use the
        // WSDL to build up the AxisService since the port added to the Service by the client is not
        // one that will be present in the WSDL.  A null class passed in as the SEI indicates this
        // is a dispatch client.
        if (!isDynamicPort && getServiceDescriptionImpl().getWSDLWrapper() != null) {
            isAxisServiceBuiltFromWSDL = buildAxisServiceFromWSDL();
        }
        else {
            buildAxisServiceFromAnnotations();
        }
       
        if (axisService == null) {
            // TODO: RAS & NLS
            throw ExceptionFactory.makeWebServiceException("Unable to create AxisService for "
                    + createAxisServiceName());
        }

        // Save the Service QName as a parameter.
        Parameter serviceNameParameter = new Parameter();
        serviceNameParameter.setName(WSDL11ToAllAxisServicesBuilder.WSDL_SERVICE_QNAME);
        serviceNameParameter.setValue(getServiceDescription().getServiceQName());
       
        // Save the Port name.  Note: Axis does not expect a QName since the namespace for the port is the ns from the WSDL definition
        Parameter portParameter = new Parameter();
        portParameter.setName(WSDL11ToAllAxisServicesBuilder.WSDL_PORT);
        portParameter.setValue(portQName.getLocalPart());

        try {
            axisService.addParameter(serviceNameParameter);
            axisService.addParameter(portParameter);                       
        }
        catch (AxisFault e) {
            // TODO RAS
            e.printStackTrace();
        }
    }

    /*
     * This setups and builds the AxisService using only the DescriptionBuilderCompositeList
     *
     */
    private void setupAxisServiceFromDBL() {
        // TODO: Need to use MetaDataQuery validator to merge WSDL (if any) and annotations (if any)
        // Build up the AxisService.  Note that if this is a dispatch client, then we don't use the
        // WSDL to build up the AxisService since the port added to the Service by the client is not
        // one that will be present in the WSDL.  A null class passed in as the SEI indicates this
        // is a dispatch client.
     
        // If WSDL is present, it may be full or only partial.  If we can create the AxisService from
        // the WSDL, that WSDL is fully specified.  Otherwise, it is "partial WSDL".  In that case
        // we use annotaions to build the AxisService
        isAxisServiceBuiltFromWSDL = false;
        if (getServiceDescriptionImpl().getWSDLWrapper() != null) {
            isAxisServiceBuiltFromWSDL = buildAxisServiceFromWSDL();
           
        }
       
        if (!isAxisServiceBuiltFromWSDL) {
          //generateWSDL(composite);
            buildAxisServiceFromAnnotations();
        }
       
        if (axisService == null) {
            // TODO: RAS & NLS
            throw ExceptionFactory.makeWebServiceException("Unable to create AxisService for "
                    + createAxisServiceName());
        }

        //Save the Port Type name
        Parameter portTypeNameParameter = new Parameter();
        portTypeNameParameter.setName(MDQConstants.WSDL_PORTTYPE_NAME);
        portTypeNameParameter.setValue(getName());
       
        // Save the Service QName as a parameter.
        Parameter serviceNameParameter = new Parameter();
        serviceNameParameter.setName(MDQConstants.WSDL_SERVICE_QNAME);
        serviceNameParameter.setValue(getServiceDescription().getServiceQName());
       
        // Save the Port name.  Note: Axis does not expect a QName since the namespace
        //   for the port is the ns from the WSDL definition
        Parameter portParameter = new Parameter();
        portParameter.setName(MDQConstants.WSDL_PORT);
        portParameter.setValue(getPortQName().getLocalPart());

       
        //Save the fully qualified class name for the serviceImpl
        Parameter serviceClassNameParameter = new Parameter();
        serviceClassNameParameter.setName(MDQConstants.SERVICE_CLASS);
        serviceClassNameParameter.setValue(DescriptionUtils.javifyClassName(composite.getClassName()));
          
         try {          
            axisService.addParameter(portTypeNameParameter);
            axisService.addParameter(serviceNameParameter);
            axisService.addParameter(portParameter);                       
            axisService.addParameter(serviceClassNameParameter);
        }
        catch (AxisFault e) {
            // TODO RAS
            e.printStackTrace();
        }
    }

    private boolean buildAxisServiceFromWSDL() {
        boolean isBuiltFromWSDL = false;
      try {
       
        // TODO: Change this to use WSDLToAxisServiceBuilder superclass
        // Note that the axis service builder takes only the localpart of the port qname.
        // TODO:: This should check that the namespace of the definition matches the namespace of the portQName per JAXRPC spec
       
        WSDL11ToAxisServiceBuilder serviceBuilder =
          new WSDL11ToAxisServiceBuilder( getServiceDescriptionImpl().getWSDLWrapper().getDefinition(),
              getServiceDescription().getServiceQName(),
              getPortQName().getLocalPart());
       
        if (getServiceDescriptionImpl().isDBCMap()) {
           //this.class.getClass().getClassLoader();
          URIResolverImpl uriResolver =
              new URIResolverImpl(composite.getClassLoader());
          serviceBuilder.setCustomResolver(uriResolver);
        }
        else {
          ClassLoader classLoader = (ClassLoader) AccessController.doPrivileged(new
              PrivilegedAction() {
                public Object run() {
                  return Thread.currentThread().getContextClassLoader();
                }
            });
          URIResolverImpl uriResolver = new URIResolverImpl(classLoader);
          serviceBuilder.setCustomResolver(uriResolver);
        }
       
        // TODO: Currently this only builds the client-side AxisService;
        // it needs to do client and server somehow.
        // Patterned after AxisService.createClientSideAxisService       
        if (getServiceDescriptionImpl().isServerSide())
          serviceBuilder.setServerSide(true);
        else
          serviceBuilder.setServerSide(false);
       
        axisService = serviceBuilder.populateService();
        axisService.setName(createAxisServiceName());
            isBuiltFromWSDL = true;
           
      } catch (AxisFault e) {
        // REVIEW: If we couldn't use the WSDL, should we fail instead of continuing to process using annotations? 
            //         Note that if we choose to fail, we need to distinguish the partial WSDL case (which can not fail)
            // TODO: RAS/NLS  Need to update the message with the appropriate inserts
//        log.warn(Messages.getMessage("warnAxisFault", e.toString()), e);
            String wsdlLocation = (getServiceDescriptionImpl().getWSDLLocation() != null) ? getServiceDescriptionImpl().getWSDLLocation().toString() : null;
            String implClassName = null;
            if (getServiceDescriptionImpl().isDBCMap()) {
                implClassName = composite.getClassName();
            }
            else {
                implClassName = (implOrSEIClass != null) ? implOrSEIClass.getName() : null;
            }
            log.warn("The WSDL file could not be used due to an exception.  The WSDL will be ignored and annotations will be used.  Implementaiton class: "
                    + implClassName + "; WSDL Location: " + wsdlLocation +"; Exception: " + e.toString(), e);
            isBuiltFromWSDL = false;
            return isBuiltFromWSDL;
      }
        return isBuiltFromWSDL;
    }
   
    private void buildAxisServiceFromAnnotations() {
        // TODO: Refactor this to create from annotations.
        String serviceName = null;
        if (portQName != null) {
            serviceName = createAxisServiceName();
        }
        else {
            // REVIEW: Can the portQName ever be null?
            // Make this service name unique.  The Axis2 engine assumes that a service it can not find is a client-side service.
            serviceName = ServiceClient.ANON_SERVICE + this.hashCode() + System.currentTimeMillis();
        }
        axisService = new AxisService(serviceName);
       
        //TODO: Set other things on AxisService here, this function may have to be
        //      moved to after we create all the AxisOperations
    }
   
    private void buildDescriptionHierachy() {
        // Build up the Description Hierachy.  Note that if this is a dynamic port, then we don't use the
        // WSDL to build up the hierachy since the port added to the Service by the client is not
        // one that will be present in the WSDL.
     
      //First, check to see if we can build this with the DBC List
      //TODO: When MDQ input is the only possible input, then we can remove the check for
      //      the DBC list, until that time the code in here may appear somewhat redundant
      if (getServiceDescriptionImpl().isDBCMap()) {
        if (!isDynamicPort && isWSDLFullySpecified())
          buildEndpointDescriptionFromWSDL();
        else
          buildEndpointDescriptionFromAnnotations();
      } else {
        //Still processing annotations from the class
          // This path was not updated
        if (!isDynamicPort && isWSDLFullySpecified()) {
          buildEndpointDescriptionFromWSDL();
        }
        else if (implOrSEIClass != null){
          // Create the rest of the description hierachy from annotations on the class.
          // If there is no SEI class, then this is a Distpach case, and we currently
          // don't create the rest of the description hierachy (since it is not an SEI and thus
          // not operation-based client.
          buildEndpointDescriptionFromAnnotations();
        }
      }
    }
   
    private void buildEndpointDescriptionFromWSDL() {
        Definition wsdlDefinition = getServiceDescriptionImpl().getWSDLWrapper().getDefinition();
        javax.wsdl.Service wsdlService = wsdlDefinition.getService(getServiceDescription().getServiceQName());
        if (wsdlService == null) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("serviceDescErr2", createAxisServiceName()));
        }
       
        Map wsdlPorts = wsdlService.getPorts();
        boolean wsdlPortFound = false;
        if (wsdlPorts != null && wsdlPorts.size() > 0) {
            Iterator wsdlPortIterator = wsdlPorts.values().iterator();
 
            while (wsdlPortIterator.hasNext() && !wsdlPortFound) {
                Port wsdlPort = (Port) wsdlPortIterator.next();
                // Note the namespace is not included on the WSDL Port.
                if (wsdlPort.getName().equals(portQName.getLocalPart())) {
                   
                    // Build the EndpointInterface based on the specified SEI if there is one
                    // or on the service impl class (i.e. an implicit SEI).
                    if (getServiceDescriptionImpl().isDBCMap()) {
                        String seiClassName = getAnnoWebServiceEndpointInterface();
                        if (DescriptionUtils.isEmpty(seiClassName)) {
                            // No SEI specified, so use the service impl as an implicit SEI
                            endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(composite, true, this);
                        } else {
                            // Otherwise, build the EID based on the SEI composite
                            endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(
                                        getServiceDescriptionImpl().getDBCMap().get(seiClassName),
                                        false,
                                        this);
                        }

                    }
                    else {
                        // Create the Endpoint Interface Description based on the WSDL.
                        endpointInterfaceDescription = new EndpointInterfaceDescriptionImpl(this);
                        // Update the EndpointInterfaceDescription created with WSDL with information from the
                        // annotations in the SEI
                        ((EndpointInterfaceDescriptionImpl) endpointInterfaceDescription).updateWithSEI(implOrSEIClass);
                    }
                    wsdlPortFound = true;
                }
            }
        }
       
        if (!wsdlPortFound) {
            // TODO: NLS and RAS
            throw ExceptionFactory.makeWebServiceException("WSDL Port not found for port " + portQName.getLocalPart())
        }
    }
   
    /**
     * Adds the anonymous axis operations to the AxisService.  Note that this is only needed on
     * the client side, and they are currently used in two cases
     * (1) For Dispatch clients (which don't use SEIs and thus don't use operations)
     * (2) TEMPORARLIY for Services created without WSDL (and thus which have no AxisOperations created)
     *  See the AxisInvocationController invoke methods for more details.
     * 
     *   Based on ServiceClient.createAnonymouService
     */
    private void addAnonymousAxisOperations() {
        if (axisService != null) {
            OutOnlyAxisOperation outOnlyOperation = new OutOnlyAxisOperation(ServiceClient.ANON_OUT_ONLY_OP);
            axisService.addOperation(outOnlyOperation);

            OutInAxisOperation outInOperation = new OutInAxisOperation(ServiceClient.ANON_OUT_IN_OP);
            axisService.addOperation(outInOperation);
        }
    }
   
    public ServiceClient getServiceClient(){
        try {
            if(serviceClient == null) {
                ConfigurationContext configCtx = getServiceDescription().getAxisConfigContext();
                AxisService axisSvc = getAxisService();
                serviceClient = new ServiceClient(configCtx, axisSvc);
            }
        } catch (AxisFault e) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("serviceClientCreateError"), e);
        }
        return serviceClient;
    }
    //This should eventually be deprecated in favor 'createAxisServiceNameFromDBL
    private String createAxisServiceName() {
        String portName = null;
        if (portQName != null) {
            portName = portQName.getLocalPart();
        }
        else {
            portName = "NoPortNameSpecified";

        }
        return getServiceDescription().getServiceQName().getLocalPart() + "." + portName;
    }

    public boolean isWSDLFullySpecified() {
        return isAxisServiceBuiltFromWSDL;
    }
   
    public boolean isProviderBased() {
        return webServiceProviderAnnotation != null;
    }
   
    public boolean isEndpointBased() {
        return webServiceAnnotation != null;
    }

    // ===========================================
    // ANNOTATION: WebService and WebServiceProvider
    // ===========================================
   
    public String getAnnoWebServiceWSDLLocation() {
      if (annotation_WsdlLocation == null) {
       
        if (getAnnoWebService() != null) {
        annotation_WsdlLocation = getAnnoWebService().wsdlLocation();               
          
           //If this is not an implicit SEI, then make sure that its not on the SEI
        if (getServiceDescriptionImpl().isDBCMap()) {
          if (!DescriptionUtils.isEmpty(getAnnoWebServiceEndpointInterface())) {
           
              DescriptionBuilderComposite seic =
                getServiceDescriptionImpl().getDBCMap().get(composite.getWebServiceAnnot().endpointInterface());
              if (!DescriptionUtils.isEmpty(seic.getWebServiceAnnot().wsdlLocation())) {
                annotation_WsdlLocation = seic.getWebServiceAnnot().wsdlLocation();
              }
            }
        }
        }
        else if (getAnnoWebServiceProvider() != null
            && !DescriptionUtils.isEmpty(getAnnoWebServiceProvider().wsdlLocation())) {
          annotation_WsdlLocation = getAnnoWebServiceProvider().wsdlLocation();
        }
        else {
          // There is no default value per JSR-181 MR Sec 4.1 pg 16
          annotation_WsdlLocation = "";
        }
      }
      return annotation_WsdlLocation;
    }

    public String getAnnoWebServiceServiceName() {
        if (annotation_ServiceName == null) {
            if (getAnnoWebService() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebService().serviceName())) {
                annotation_ServiceName = getAnnoWebService().serviceName();
            }
            else if (getAnnoWebServiceProvider() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebServiceProvider().serviceName())) {
                annotation_ServiceName = getAnnoWebServiceProvider().serviceName();
            }
            else {
                // Default value is the "simple name" of the class or interface + "Service"
                // Per JSR-181 MR Sec 4.1, pg 15
              if (getServiceDescriptionImpl().isDBCMap()) {
                  annotation_ServiceName = DescriptionUtils.getSimpleJavaClassName(composite.getClassName()) + "Service";
              } else {
                    annotation_ServiceName = DescriptionUtils.getSimpleJavaClassName(implOrSEIClass) + "Service";
              }
            }
        }
        return annotation_ServiceName;
    }
   
    public String getAnnoWebServicePortName() {
        if (annotation_PortName == null) {
            if (getAnnoWebService() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebService().portName())) {
                annotation_PortName = getAnnoWebService().portName();
            }
            else if (getAnnoWebServiceProvider() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebServiceProvider().portName())) {
                annotation_PortName = getAnnoWebServiceProvider().portName();
            }
            else {
                // Default the value
                if (isProviderBased()) {
                    // This is the @WebServiceProvider annotation path
                    // Default value is not specified in JSR-224, but we can assume it is
                    // similar to the default in the WebService case, however there is no
                    // name attribute for a WebServiceProvider.  So in this case we use
                    // the default value for WebService.name per JSR-181 MR sec 4.1 pg 15.
                    // Note that this is really the same thing as the call to getWebServiceName()
                    // in the WebService case; it is done sepertely just to be clear there is no
                    // name element on the WebServiceProvider annotation
                 
                  annotation_PortName = (getServiceDescriptionImpl().isDBCMap()) ?
                            DescriptionUtils.getSimpleJavaClassName(composite.getClassName()) + "Port"
                       : DescriptionUtils.getSimpleJavaClassName(implOrSEIClass) + "Port";
               }
                else {
                    // This is the @WebService annotation path
                    // Default value is the @WebService.name of the class or interface + "Port"
                    // Per JSR-181 MR Sec 4.1, pg 15
                    annotation_PortName = getAnnoWebServiceName() + "Port";
                }
            }
        }
        return annotation_PortName;
    }

    public String getAnnoWebServiceTargetNamespace() {
        if (annotation_TargetNamespace == null) {
            if (getAnnoWebService() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebService().targetNamespace())) {
                annotation_TargetNamespace = getAnnoWebService().targetNamespace();
            }
            else if (getAnnoWebServiceProvider() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebServiceProvider().targetNamespace())) {
                annotation_TargetNamespace = getAnnoWebServiceProvider().targetNamespace();
            }
            else {
                // Default value per JSR-181 MR Sec 4.1 pg 15 defers to "Implementation defined,
                // as described in JAX-WS 2.0, section 3.2" which is JAX-WS 2.0 Sec 3.2, pg 29.
                // FIXME: Hardcoded protocol for namespace
              if (getServiceDescriptionImpl().isDBCMap())
                annotation_TargetNamespace =
                        DescriptionUtils.makeNamespaceFromPackageName(DescriptionUtils.getJavaPackageName(composite.getClassName()), "http");
              else
                annotation_TargetNamespace =
                        DescriptionUtils.makeNamespaceFromPackageName(DescriptionUtils.getJavaPackageName(implOrSEIClass), "http");

            }
        }
        return annotation_TargetNamespace;
    }
   
   
    // ===========================================
    // ANNOTATION: WebServiceProvider
    // ===========================================

    public WebServiceProvider getAnnoWebServiceProvider() {
        return webServiceProviderAnnotation;
    }

    // ===========================================
    // ANNOTATION: WebService
    // ===========================================

    public WebService getAnnoWebService() {
        return webServiceAnnotation;
    }
   
    public String getAnnoWebServiceEndpointInterface() {
        // TODO: Validation: Not allowed on WebServiceProvider
        if (webService_EndpointInterface == null) {
            if (!isProviderBased() && getAnnoWebService() != null
                    && !DescriptionUtils.isEmpty(getAnnoWebService().endpointInterface())) {
                webService_EndpointInterface = getAnnoWebService().endpointInterface();
            }
            else {
                // This element is not valid on a WebServiceProvider annotation
                // REVIEW: Is this a correct thing to return if this is called against a WebServiceProvier
                //         which does not support this element?
                webService_EndpointInterface = "";
            }
        }
        return webService_EndpointInterface;
    }
   
    public String getAnnoWebServiceName() {
        // TODO: Validation: Not allowed on WebServiceProvider
     
      //TODO: Per JSR109 v1.2 Sec. 5.3.2.1
      //      If not specified then we can use the default value as specified in JSR 181
      //    (but only if it is unique within the module)...or If the name is
      //    not specified in the Service Implementation Bean then fully
      //    qualified name of the Bean class is used to guarantee uniqueness
      //    If the above is not unique then fully qualified name of the
      //    Bean class is used to guarantee uniqueness
     
      if (webService_Name == null) {
        if (!isProviderBased()) {
          if (getAnnoWebService() != null
              && !DescriptionUtils.isEmpty(getAnnoWebService().name())) {
            webService_Name = getAnnoWebService().name();
           }
          else {
            if (getServiceDescriptionImpl().isDBCMap()) {
              //The name is the simple name of the class or interface
              webService_Name = DescriptionUtils.getSimpleJavaClassName(composite.getClassName());
            } else {
              // Default per JSR-181 Sec 4.1, pg 15
              webService_Name = DescriptionUtils.getSimpleJavaClassName(implOrSEIClass);
            }
          }                 
        }
        else {
          // This element is not valid on a WebServiceProvider annotation
          // REVIEW: Is this a correct thing to return if this is called against a WebServiceProvier
          //         which does not support this element?
          webService_Name = "";
        }
      }
        return webService_Name;
    }
   
    // ===========================================
    // ANNOTATION: ServiceMode
    // ===========================================
    public ServiceMode getAnnoServiceMode() {
       
      if (serviceModeAnnotation == null) {
          if (getServiceDescriptionImpl().isDBCMap()) {
            serviceModeAnnotation = composite.getServiceModeAnnot();
          } else
            if (implOrSEIClass != null) {
              serviceModeAnnotation = (ServiceMode) implOrSEIClass.getAnnotation(ServiceMode.class);
            }
          }
        }
        return serviceModeAnnotation;
    }
   
    public Service.Mode getServiceMode() {
        // REVIEW: WSDL/Anno Merge
        return getAnnoServiceModeValue();
    }
   
    public Service.Mode getAnnoServiceModeValue() {
        // This annotation is only valid on Provider-based endpoints.
        if (isProviderBased() && serviceModeValue == null) {
            if (getAnnoServiceMode() != null) {
                serviceModeValue = getAnnoServiceMode().value();
            }
            else {
                serviceModeValue = ServiceMode_DEFAULT;
            }
        }
        return serviceModeValue;
    }
   
    // ===========================================
    // ANNOTATION: BindingType
    // ===========================================

    public BindingType getAnnoBindingType() {
      if (bindingTypeAnnotation == null) {
          if (getServiceDescriptionImpl().isDBCMap()) {
            bindingTypeAnnotation = composite.getBindingTypeAnnot();
          } else
            if (implOrSEIClass != null) {
                    bindingTypeAnnotation = (BindingType) implOrSEIClass.getAnnotation(BindingType.class);
            }
          }
        }
        return bindingTypeAnnotation;
    }
   
    public String getBindingType() {
        // REVIEW: Implement WSDL/Anno merge?
        return getAnnoBindingTypeValue();
    }
   
    public String getAnnoBindingTypeValue() {
        if (bindingTypeValue == null) {
            if (getAnnoBindingType() != null) {
                bindingTypeValue = getAnnoBindingType().value();
            }
            else {
                // No BindingType annotation present; use default value
                bindingTypeValue = BindingType_DEFAULT;
            }
        }
        return bindingTypeValue;
    }

    // ===========================================
    // ANNOTATION: HandlerChain
    // ===========================================

    /**
     * Returns a live list describing the handlers on this port.
     * TODO: This is currently returning List<String>, but it should return a HandlerDescritpion
     * object that can represent a handler description from various Metadata (annotation, deployment descriptors, etc);
     * use JAX-WS Appendix B Handler Chain Configuration File Schema as a starting point for HandlerDescription.
     * 
     * @return A List of handlers for this port.  The actual list is returned, and therefore can be modified.
     */
    public List<String> getHandlerList() {
        return handlerList;
    }
    private Definition getWSDLDefinition() {
        return ((ServiceDescriptionWSDL) getServiceDescription()).getWSDLDefinition();
    }
    public javax.wsdl.Service getWSDLService() {
        Definition defn = getWSDLDefinition();
        if (defn != null) {
            return defn.getService(getServiceQName());
        }
        else {
            return null;
        }
    }
    public Port getWSDLPort() {
        javax.wsdl.Service service = getWSDLService();
        if (service != null) {
            return service.getPort(getPortQName().getLocalPart());
        }
        else {
            return null;
        }
    }
    public Binding getWSDLBinding() {
        Binding wsdlBinding = null;
        Port wsdlPort = getWSDLPort();
        Definition wsdlDef = getWSDLDefinition();
        if (wsdlPort != null && wsdlDef != null) {
            wsdlBinding = wsdlPort.getBinding();
        }
        return wsdlBinding;
    }
   
    public String getWSDLBindingType() {
        String wsdlBindingType = null;
        Binding wsdlBinding = getWSDLBinding();
        if (wsdlBinding != null) {
            // If a WSDL binding was found, we need to find the proper extensibility
            // element and return the namespace.  The namespace will be different
            // for SOAP 1.1 vs. SOAP 1.2 bindings and HTTP.
            // TODO: What do we do if no extensibility element exists?
            List<ExtensibilityElement> elements = wsdlBinding.getExtensibilityElements();
            Iterator<ExtensibilityElement> itr = elements.iterator();
            while (itr.hasNext()) {
                ExtensibilityElement e = itr.next();
                if (javax.wsdl.extensions.soap.SOAPBinding.class.isAssignableFrom(e.getClass())) {
                    javax.wsdl.extensions.soap.SOAPBinding soapBnd = (javax.wsdl.extensions.soap.SOAPBinding) e;
                    wsdlBindingType = soapBnd.getElementType().getNamespaceURI();
                    break;
                }
                else if (SOAP12Binding.class.isAssignableFrom(e.getClass())) {
                    SOAP12Binding soapBnd = (SOAP12Binding) e;
                    wsdlBindingType = soapBnd.getElementType().getNamespaceURI();
                    break;
                }
                else if (HTTPBinding.class.isAssignableFrom(e.getClass())) {
                    HTTPBinding httpBnd = (HTTPBinding) e;
                    wsdlBindingType = httpBnd.getElementType().getNamespaceURI();
                    break;
                }
            }
        }
        return wsdlBindingType;
    }
   
    public String getName() {
        return getAnnoWebServiceName();
    }
    public String getTargetNamespace() {
        return getAnnoWebServiceTargetNamespace();
    }
   
    public PortInfo getPortInfo() {
        if (portInfo == null) {
            portInfo = new PortInfoImpl(getServiceQName(), getPortQName(), getBindingType());
        }
        return portInfo;
    }
    public void setClientBindingID(String clientBindingID) {
       
        if (clientBindingID == null) {
            this.clientBindingID = DEFAULT_CLIENT_BINDING_ID;
        }
        else if (validateClientBindingID(clientBindingID)) {
            this.clientBindingID = clientBindingID;
        }
        else {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("addPortErr0", getPortQName().toString()));
        }
    }
    private boolean validateClientBindingID(String bindingId) {
        boolean isValid = true;
        if (bindingId != null && !(bindingId.equals(SOAPBinding.SOAP11HTTP_BINDING) ||
                bindingId.equals(javax.xml.ws.http.HTTPBinding.HTTP_BINDING) ||
                bindingId.equals(SOAPBinding.SOAP12HTTP_BINDING) ||
                bindingId.equals(SOAPBinding.SOAP11HTTP_MTOM_BINDING) ||
                bindingId.equals(SOAPBinding.SOAP12HTTP_MTOM_BINDING))) {
            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("addPortErr0", getPortQName().toString()));
        }
        return isValid;
    }
   
    public String getClientBindingID() {
        if (clientBindingID == null) {
            if (getWSDLDefinition() != null) {
                clientBindingID = getWSDLBindingType();
            }
            else {
                clientBindingID = DEFAULT_CLIENT_BINDING_ID;
            }
        }
        return clientBindingID;
    }
   
    public void setEndpointAddress(String endpointAddress) {
        // REVIEW: Should this be called whenever BindingProvider.ENDPOINT_ADDRESS_PROPERTY is set by the client?
        if (!DescriptionUtils.isEmpty(endpointAddress)) {
            this.endpointAddress = endpointAddress;
        }
        else {
            // Since a port can be added without setting an endpoint address, this is not an error.
            if (log.isDebugEnabled())
                log.debug("A null or empty endpoint address was attempted to be set", new Throwable("Stack Traceback"));
        }
    }
   
    public String getEndpointAddress() {
        if (endpointAddress == null) {
            // If the endpointAddress has not been set explicitly by a call to setEndpointAddress()
            // then try to get it from the WSDL
            endpointAddress = getWSDLSOAPAddress();
        }
        return endpointAddress;
    }
   
    /**
     * Return the SOAP Address from the WSDL for this port.
     * @return The SOAP Address from the WSDL for this port or null.
     */
    public String getWSDLSOAPAddress() {
        if (wsdlSOAPAddress == null) {
            Port wsdlPort = getWSDLPort();
            if (wsdlPort != null) {
                // The port is in the WSDL, so see if it has a SOAP address extensibility element specified.
                List extElementList = wsdlPort.getExtensibilityElements();
                for (Object listElement : extElementList) {
                    ExtensibilityElement extElement = (ExtensibilityElement) listElement;
                    if (isSOAPAddressElement(extElement)) {
                        String soapAddress = getSOAPAddressFromElement(extElement);
                        if (!DescriptionUtils.isEmpty(soapAddress)) {
                            wsdlSOAPAddress = soapAddress;
                        }
                    }
                }
            }
        }
        return wsdlSOAPAddress;
    }
   
    /**
     * Determine if the WSDL Extensibility element corresponds to the SOAP Address element.
     * @param exElement
     * @return
     */
    static boolean isSOAPAddressElement(ExtensibilityElement exElement){
        boolean isAddress = false;
        if (exElement != null) {
            isAddress = (SOAP_11_ADDRESS_ELEMENT.equals(exElement.getElementType())
                        ||
                        (SOAP_12_ADDRESS_ELEMENT.equals(exElement.getElementType())));
        }
        return isAddress;
    }
   
    static String getSOAPAddressFromElement(ExtensibilityElement extElement) {
        String returnAddress = null;
       
        if (extElement != null) {
            if (SOAP_11_ADDRESS_ELEMENT.equals(extElement.getElementType())) {
                returnAddress = ((SOAPAddress) extElement).getLocationURI();
            }
            else if (SOAP_12_ADDRESS_ELEMENT.equals(extElement.getElementType())) {
                returnAddress = ((SOAP12Address) extElement).getLocationURI();
            }
        }
       
        return returnAddress;
    }
   
    /**
     * Selects a port to use in the case where a portQName was not specified by the client on the
     * Service.getPort(Class) call.  If WSDL is present, then an appropriate port is looked for under
     * the service element, and an exception is thrown if none can be found.  If WSDL is not present,
     * then the selected port is simply the one determined by annotations.
     * @return A QName representing the port that is to be used.
     */
    private QName selectPortToUse() {
        QName portToUse = null;
        // If WSDL Service for this port is present, then we'll find an appropriate port defined in there and set
        // the name accordingly.  If no WSDL is present, the the PortQName getter will use annotations to set the value.
        if (getWSDLService() != null) {
            portToUse = selectWSDLPortToUse();
        }
        else {
            // No WSDL, so the port to use is the one defined by the annotations.
            portToUse = getPortQName();
        }
        return portToUse;
    }
   
    /**
     * Look through the WSDL Service for a port that should be used.  If none can be
     * found, then throw an exception.
     * @param wsdlService
     * @return A QName representing the port from the WSDL that should be used.
     */
    private QName selectWSDLPortToUse() {
        QName wsdlPortToUse = null;
       
        // To select which WSDL Port to use, we do the following
        // 1) Find the subset of all ports under the service that use the PortType represented by the SEI
        // 2) From the subset in (1) find all those ports that specify a SOAP Address
        // 3) Use the first port from (2)
        // REVIEW: Should we be looking at the binding type or something else to determin which subset of ports to use;
        //         i.e. instead of just finding ports that specify a SOAP Address?
       
        // Per JSR-181,
        // - The portType name corresponds to the WebService.name annotation value, which is
        //   returned by getName()
        // - The portType namespace corresponds to the WebService.targetNamespace annotation, which
        //   is returned by getTargetNamespace()
        String portTypeLP = getName();
        String portTypeTNS = getTargetNamespace();
        QName portTypeQN = new QName(portTypeTNS, portTypeLP);

        ServiceDescriptionWSDL serviceDescWSDL = (ServiceDescriptionWSDL) getServiceDescription();

        List<Port> wsdlPortsUsingPortType = serviceDescWSDL.getWSDLPortsUsingPortType(portTypeQN);
        List<Port> wsdlPortsUsingSOAPAddresses = serviceDescWSDL.getWSDLPortsUsingSOAPAddress(wsdlPortsUsingPortType);
        if (wsdlPortsUsingSOAPAddresses != null && !wsdlPortsUsingSOAPAddresses.isEmpty()) {
            // We return the first port that uses the particluar PortType and has a SOAP address.
            // HOWEVER, that is not necessarily the first one in the WSDL that meets that criteria! 
            // The problem is that WSDL4J Service.getPorts(), which is used to get a Map of ports under the service
            // DOES NOT return the ports in the order they are defined in the WSDL. 
            // Therefore, we can't necessarily predict which one we'll get back as the "first" one in the collection.
            // REVIEW: Note the above comment; is there anything more predictible and determinstic we can do?
            Port portToUse = (Port) wsdlPortsUsingSOAPAddresses.toArray()[0];
            String portLocalPart = portToUse.getName();
            String portNamespace = serviceDescWSDL.getWSDLService().getQName().getNamespaceURI();
            wsdlPortToUse = new QName(portNamespace, portLocalPart);
        }

        return wsdlPortToUse;
    }
    private WsdlComposite generateWSDL(DescriptionBuilderComposite dbc) {
     
      WsdlComposite wsdlComposite = null;
       Definition defn = dbc.getWsdlDefinition();
      if (defn == null || !isAxisServiceBuiltFromWSDL) {
       
          //Invoke the callback for generating the wsdl
            if (dbc.getCustomWsdlGenerator() != null) {
              String implName = null;
              if(axisService == null) {
                implName = DescriptionUtils.javifyClassName(composite.getClassName());
              }
              else {
                implName = (String)axisService.getParameterValue(MDQConstants.SERVICE_CLASS);
              }
              wsdlComposite =
                dbc.getCustomWsdlGenerator().generateWsdl(implName, getBindingType());
              if (wsdlComposite != null) {
                wsdlComposite.setWsdlFileName((this.getAnnoWebServiceServiceName() + ".wsdl").toLowerCase());
               
                Definition wsdlDef = wsdlComposite.getRootWsdlDefinition();
             
                try {
                  WSDL4JWrapper wsdl4jWrapper = new WSDL4JWrapper(dbc.getWsdlURL(), wsdlDef);
                  getServiceDescriptionImpl().setGeneratedWsdlWrapper(wsdl4jWrapper);
                } catch (Exception e) {
                  throw ExceptionFactory.makeWebServiceException("EndpointDescriptionImpl: WSDLException thrown when attempting to instantiate WSDL4JWrapper ");
                }
              } else {
                  //TODO:Determine if we should always throw an exception on this, or at this point
                    //throw ExceptionFactory.makeWebServiceException("EndpointDescriptionImpl: Unable to find custom WSDL generator");
              }
            } else {
              //TODO:Determine if we should always throw an exception on this, or at this point
                throw ExceptionFactory.makeWebServiceException("EndpointDescriptionImpl: Unable to find custom WSDL generator");
            }
      }
      return wsdlComposite;
    }
   
    /**
     * Return the class for this name
     * @return Class
     */
    private static Class forName(final String className, final boolean initialize, final ClassLoader classloader) throws ClassNotFoundException {
        // NOTE: This method must remain protected because it uses AccessController
        Class cl = null;
        try {
            cl = (Class) AccessController.doPrivileged(
                    new PrivilegedExceptionAction() {
                        public Object run() throws ClassNotFoundException {
                            return Class.forName(className, initialize, classloader);   
                        }
                    }
                  )
        } catch (PrivilegedActionException e) {
            if (log.isDebugEnabled()) {
                log.debug("Exception thrown from AccessController: " + e);
            }
            throw (ClassNotFoundException) e.getException();
        }
       
        return cl;
    }
   
    /**
     * @return ClassLoader
     */
    private static ClassLoader getContextClassLoader() {
        // NOTE: This method must remain private because it uses AccessController
        ClassLoader cl = null;
        try {
            cl = (ClassLoader) AccessController.doPrivileged(
                    new PrivilegedExceptionAction() {
                        public Object run() throws ClassNotFoundException {
                            return Thread.currentThread().getContextClassLoader();     
                        }
                    }
                  )
        } catch (PrivilegedActionException e) {
            if (log.isDebugEnabled()) {
                log.debug("Exception thrown from AccessController: " + e);
            }
            throw (RuntimeException) e.getException();
        }
       
        return cl;
    }
   
    public String toString() {
        final String newline = "\n";
        final String sameline = "; ";
        StringBuffer string = new StringBuffer();

        string.append(super.toString());
        string.append(newline);
        string.append("Name: " + getName());
        string.append(sameline);
        string.append("Endpoint Address: " + getEndpointAddress());
        //
        string.append(newline);
        string.append("ServiceQName: " + getServiceQName());
        string.append(sameline);
        string.append("PortQName: " + getPortQName());
        string.append(sameline);
        string.append("TargetNamespace: " + getTargetNamespace());
        //
        string.append(newline);
        string.append("Service Mode: " + getServiceMode());
        string.append(sameline);
        string.append("Binding Type: " + getBindingType());
        string.append(sameline);
        string.append("Client Binding Type: " + getClientBindingID());
        //
        string.append(newline);
        string.append("Is provider-based: " + (isProviderBased() == true));
        string.append(sameline);
        string.append("Is proxy-based: " + (isEndpointBased() == true));
        string.append(sameline);
        string.append("Is WSDL fully specified: " + (isWSDLFullySpecified() == true));
        //
        string.append(newline);
        string.append("Handler List: " + getHandlerList());
        //
        string.append(newline);
        string.append("AxisService: " + getAxisService());
        //
        string.append(newline);
        EndpointInterfaceDescription endpointInterfaceDesc = getEndpointInterfaceDescription();
        if (endpointInterfaceDesc != null) {
            string.append("EndpointInterfaceDescription: " + endpointInterfaceDesc.toString());
        }
        else {
            string.append("EndpointInterfaceDescription is null.");
        }
       
        return string.toString();
    }
}

TOP

Related Classes of org.apache.axis2.jaxws.description.impl.EndpointDescriptionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.