/** Create a CXF Client */
  @Override
  Client createClient() throws Exception {

    // get service class
    Class<?> cls = getSEIClass();

    if (getDataFormat().equals(DataFormat.POJO)) {
      ObjectHelper.notNull(cls, CxfConstants.SERVICE_CLASS);
    }

    if (getWsdlURL() == null && cls == null) {
      // no WSDL and serviceClass specified, set our default serviceClass
      setServiceClass(org.apache.camel.component.cxf.DefaultSEI.class.getName());
      setDefaultOperationNamespace(CxfConstants.DISPATCH_NAMESPACE);
      setDefaultOperationName(CxfConstants.DISPATCH_DEFAULT_OPERATION_NAMESPACE);
      if (getDataFormat().equals(DataFormat.PAYLOAD)) {
        setSkipPayloadMessagePartCheck(true);
      }
      cls = getSEIClass();
    }

    if (cls != null) {
      // create client factory bean
      ClientProxyFactoryBean factoryBean = createClientFactoryBean(cls);

      // configure client factory bean by CXF configurer
      configure(factoryBean);

      // setup client factory bean
      setupClientFactoryBean(factoryBean, cls);

      // fill in values that have not been filled.
      QName serviceQName = null;
      try {
        serviceQName = factoryBean.getServiceName();
      } catch (IllegalStateException e) {
        // It throws IllegalStateException if serviceName has not been set.
      }

      if (serviceQName == null && getServiceLocalName() != null) {
        factoryBean.setServiceName(new QName(getServiceNamespace(), getServiceLocalName()));
      }
      if (factoryBean.getEndpointName() == null && getEndpointLocalName() != null) {
        factoryBean.setEndpointName(new QName(getEndpointNamespace(), getEndpointLocalName()));
      }

      return ((ClientProxy) Proxy.getInvocationHandler(factoryBean.create())).getClient();
    } else {

      ClientFactoryBean factoryBean = createClientFactoryBean();

      // configure client factory bean by CXF configurer
      configure(factoryBean);

      // setup client factory bean
      setupClientFactoryBean(factoryBean);

      // fill in values that have not been filled.
      QName serviceQName = null;
      try {
        serviceQName = factoryBean.getServiceName();
      } catch (IllegalStateException e) {
        // It throws IllegalStateException if serviceName has not been set.
      }

      if (serviceQName == null && getServiceLocalName() != null) {
        factoryBean.setServiceName(new QName(getServiceNamespace(), getServiceLocalName()));
      }
      if (factoryBean.getEndpointName() == null && getEndpointLocalName() != null) {
        factoryBean.setEndpointName(new QName(getEndpointNamespace(), getEndpointLocalName()));
      }

      checkName(factoryBean.getEndpointName(), "endpoint/port name");
      checkName(factoryBean.getServiceName(), "service name");
      return (Client) factoryBean.create();
    }
  }
  RuntimeESBConsumer(
      final QName serviceName,
      final QName portName,
      final QName operationName,
      String publishedEndpointUrl,
      String wsdlURL,
      final boolean useServiceLocator,
      final Map<String, String> locatorProps,
      final EventFeature samFeature,
      boolean useServiceRegistry,
      final SecurityArguments securityArguments,
      Bus bus,
      boolean logging,
      final List<Header> soapHeaders,
      boolean enhancedResponse,
      Object correlationIDCallbackHandler) {
    this.operationName = operationName;
    this.samFeature = samFeature;
    this.soapHeaders = soapHeaders;
    this.enhancedResponse = enhancedResponse;

    clientFactory = new ClientFactoryBean();
    clientFactory.setServiceClass(GenericServiceClass.class);
    clientFactory
        .getServiceFactory()
        .getServiceConfigurations()
        .add(
            0,
            new AbstractServiceConfiguration() {
              @Override
              public Boolean isOperation(Method method) {
                return "invoke".equals(method.getName());
              }

              @Override
              public QName getOperationName(InterfaceInfo service, Method method) {
                return operationName;
              }

              @Override
              public Boolean isWrapped() {
                return Boolean.FALSE;
              }
            });

    clientFactory.setServiceName(serviceName);
    clientFactory.setEndpointName(portName);
    if (!useServiceRegistry) {
      String endpointUrl =
          (useServiceLocator) ? "locator://" + serviceName.getLocalPart() : publishedEndpointUrl;
      clientFactory.setAddress(endpointUrl);
    }
    if (!useServiceRegistry && null != wsdlURL) {
      clientFactory.setWsdlURL(wsdlURL);
    }
    clientFactory.setDataBinding(new SourceDataBinding());

    clientFactory.setBus(bus);

    final List<Feature> features = new ArrayList<Feature>();
    if (useServiceLocator) {
      features.add(new LocatorFeature());
    }
    if (samFeature != null) {
      features.add(samFeature);
    }
    if (correlationIDCallbackHandler != null && (!useServiceRegistry)) {
      features.add(new CorrelationIDFeature());
    }
    if (null != securityArguments.getPolicy()) {
      features.add(new WSPolicyFeature(securityArguments.getPolicy()));
    }
    if (logging) {
      features.add(new org.apache.cxf.feature.LoggingFeature());
    }
    clientFactory.setFeatures(features);

    authorizationPolicy = securityArguments.buildAuthorizationPolicy();

    Map<String, Object> clientProps =
        securityArguments.buildClientConfig(bus, useServiceRegistry, serviceName.toString());

    clientProps.put("soap.no.validate.parts", Boolean.TRUE);

    clientProps.put(
        ESBEndpointConstants.USE_SERVICE_REGISTRY_PROP, Boolean.toString(useServiceRegistry));

    if ((useServiceLocator || useServiceRegistry)
        && null != locatorProps
        && !locatorProps.isEmpty()) {
      clientProps.put(LocatorFeature.LOCATOR_PROPERTIES, locatorProps);
    }

    if (correlationIDCallbackHandler != null) {
      clientProps.put(
          CorrelationIDFeature.CORRELATION_ID_CALLBACK_HANDLER, correlationIDCallbackHandler);
    }

    clientFactory.setProperties(clientProps);
  }
  public RuntimeESBConsumer(
      final QName serviceName,
      final QName portName,
      String operationName,
      String publishedEndpointUrl,
      boolean isRequestResponse,
      final LocatorFeature slFeature,
      final EventFeature samFeature,
      final SecurityArguments securityArguments,
      final Bus bus,
      boolean logging) {
    this.operationName = operationName;
    this.isRequestResponse = isRequestResponse;
    this.samFeature = samFeature;

    clientFactory =
        new JaxWsClientFactoryBean() {
          @Override
          protected Endpoint createEndpoint() throws BusException, EndpointException {
            final Endpoint endpoint = super.createEndpoint();
            // set portType = serviceName
            InterfaceInfo ii = endpoint.getService().getServiceInfos().get(0).getInterface();
            ii.setName(serviceName);
            return endpoint;
          }
        };
    clientFactory.setServiceName(serviceName);
    clientFactory.setEndpointName(portName);
    final String endpointUrl =
        (slFeature == null) ? publishedEndpointUrl : "locator://" + serviceName.getLocalPart();
    clientFactory.setAddress(endpointUrl);
    clientFactory.setServiceClass(this.getClass());
    clientFactory.setBus(bus);
    final List<AbstractFeature> features = new ArrayList<AbstractFeature>();
    if (slFeature != null) {
      features.add(slFeature);
    }
    if (samFeature != null) {
      features.add(samFeature);
    }
    if (null != securityArguments.getPolicy()) {
      features.add(new WSPolicyFeature(securityArguments.getPolicy()));
    }
    if (logging) {
      features.add(new org.apache.cxf.feature.LoggingFeature());
    }

    clientFactory.setFeatures(features);

    if (EsbSecurity.TOKEN == securityArguments.getEsbSecurity()) {
      Map<String, Object> properties = new HashMap<String, Object>(2);
      properties.put(SecurityConstants.USERNAME, securityArguments.getUsername());
      properties.put(SecurityConstants.PASSWORD, securityArguments.getPassword());
      clientFactory.setProperties(properties);
    } else if (EsbSecurity.SAML == securityArguments.getEsbSecurity()) {
      final Map<String, String> stsPropsDef = securityArguments.getStsProperties();

      final STSClient stsClient = new STSClient(bus);
      stsClient.setWsdlLocation(stsPropsDef.get(STS_WSDL_LOCATION));
      stsClient.setServiceQName(
          new QName(stsPropsDef.get(STS_NAMESPACE), stsPropsDef.get(STS_SERVICE_NAME)));
      stsClient.setEndpointQName(
          new QName(stsPropsDef.get(STS_NAMESPACE), stsPropsDef.get(STS_ENDPOINT_NAME)));

      Map<String, Object> stsProps = new HashMap<String, Object>();

      for (Map.Entry<String, String> entry : stsPropsDef.entrySet()) {
        if (SecurityConstants.ALL_PROPERTIES.contains(entry.getKey())) {
          stsProps.put(entry.getKey(), entry.getValue());
        }
      }

      stsProps.put(SecurityConstants.USERNAME, securityArguments.getUsername());
      stsProps.put(SecurityConstants.PASSWORD, securityArguments.getPassword());
      stsClient.setProperties(stsProps);

      Map<String, Object> clientProps = new HashMap<String, Object>();
      clientProps.put(SecurityConstants.STS_CLIENT, stsClient);

      Map<String, String> clientPropsDef = securityArguments.getClientProperties();

      for (Map.Entry<String, String> entry : clientPropsDef.entrySet()) {
        if (SecurityConstants.ALL_PROPERTIES.contains(entry.getKey())) {
          clientProps.put(entry.getKey(), entry.getValue());
        }
      }
      clientProps.put(
          SecurityConstants.CALLBACK_HANDLER,
          new WSPasswordCallbackHandler(
              clientPropsDef.get(SecurityConstants.SIGNATURE_USERNAME),
              clientPropsDef.get(CONSUMER_SIGNATURE_PASSWORD)));

      clientFactory.setProperties(clientProps);
    }
  }