public IoFuture<Connection> connect(
      CallbackHandler handler, Map<String, String> saslOptions, SSLContext sslContext)
      throws IOException {
    OptionMap.Builder builder = OptionMap.builder();
    builder.addAll(configuration.getOptionMap());
    builder.set(SASL_POLICY_NOANONYMOUS, Boolean.FALSE);
    builder.set(SASL_POLICY_NOPLAINTEXT, Boolean.FALSE);
    if (isLocal() == false) {
      builder.set(Options.SASL_DISALLOWED_MECHANISMS, Sequence.of(JBOSS_LOCAL_USER));
    }
    List<Property> tempProperties =
        new ArrayList<Property>(saslOptions != null ? saslOptions.size() : 1);
    tempProperties.add(Property.of("jboss.sasl.local-user.quiet-auth", "true"));
    if (saslOptions != null) {
      for (String currentKey : saslOptions.keySet()) {
        tempProperties.add(Property.of(currentKey, saslOptions.get(currentKey)));
      }
    }
    builder.set(Options.SASL_PROPERTIES, Sequence.of(tempProperties));

    builder.set(Options.SSL_ENABLED, true);
    builder.set(Options.SSL_STARTTLS, true);

    CallbackHandler actualHandler = handler != null ? handler : new AnonymousCallbackHandler();
    return endpoint.connect(uri, builder.getMap(), actualHandler, sslContext);
  }
  /**
   * Create and setup the remoting connection
   *
   * @throws Exception
   */
  @BeforeClass
  public static void beforeTestClass() throws Exception {
    final Endpoint endpoint =
        Remoting.createEndpoint("ejb-remote-client-endpoint", OptionMap.EMPTY);
    endpoint.addConnectionProvider(
        "remote",
        new RemoteConnectionProviderFactory(),
        OptionMap.create(Options.SSL_ENABLED, Boolean.FALSE));

    // open a connection
    final int ejbRemotingPort =
        EJBRemoteManagementUtil.getEJBRemoteConnectorPort("localhost", 9999);
    final IoFuture<Connection> futureConnection =
        endpoint.connect(
            new URI("remote://localhost:" + ejbRemotingPort),
            OptionMap.create(Options.SASL_POLICY_NOANONYMOUS, Boolean.FALSE),
            new AnonymousCallbackHandler());
    connection = IoFutureHelper.get(futureConnection, 5, TimeUnit.SECONDS);
  }
  private synchronized void createConnection() {
    try {
      endpoint = Remoting.createEndpoint("endpoint", OptionMap.EMPTY);
      endpoint.addConnectionProvider(
          "remote",
          new RemoteConnectionProviderFactory(),
          OptionMap.create(Options.SSL_ENABLED, Boolean.FALSE));
      endpoint.addConnectionProvider(
          "http-remoting",
          new HttpUpgradeConnectionProviderFactory(),
          OptionMap.create(Options.SSL_ENABLED, Boolean.FALSE));
      endpoint.addConnectionProvider(
          "https-remoting",
          new HttpUpgradeConnectionProviderFactory(),
          OptionMap.create(Options.SSL_ENABLED, Boolean.TRUE));

      // open a connection
      final IoFuture<Connection> futureConnection =
          endpoint.connect(
              new URI(hostUrl),
              OptionMap.create(
                  Options.SASL_POLICY_NOANONYMOUS,
                  Boolean.FALSE,
                  Options.SASL_POLICY_NOPLAINTEXT,
                  Boolean.FALSE),
              callbackHandler);
      connection = IoFutureHelper.get(futureConnection, 30L, TimeUnit.SECONDS);

      final EJBClientContext ejbClientContext = EJBClientContext.create(classLoader);
      ejbClientContext.registerConnection(connection);

      this.clientContext = ejbClientContext;
    } catch (IOException e) {
      throw new RuntimeException(e);
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }
  }
  public NamingProvider createProvider(
      final URI providerUri, final FastHashtable<String, Object> env) throws NamingException {
    // Legacy naming constants
    final Endpoint endpoint = getEndpoint(env);
    final String callbackClass = getStringProperty(CALLBACK_HANDLER_KEY, env);
    final String userName = getStringProperty(Context.SECURITY_PRINCIPAL, env);
    final String password = getStringProperty(Context.SECURITY_CREDENTIALS, env);
    final String passwordBase64 = getStringProperty(PASSWORD_BASE64_KEY, env);
    final String realm = getStringProperty(REALM_KEY, env);

    boolean useSeparateConnection =
        Boolean.parseBoolean(String.valueOf(env.get(USE_SEPARATE_CONNECTION)));

    AuthenticationContext captured = AuthenticationContext.captureCurrent();
    AuthenticationConfiguration mergedConfiguration =
        AUTH_CONFIGURATION_CLIENT.getAuthenticationConfiguration(providerUri, captured);
    if (callbackClass != null && (userName != null || password != null)) {
      throw Messages.log.callbackHandlerAndUsernameAndPasswordSpecified();
    }
    if (callbackClass != null) {
      final ClassLoader classLoader = secureGetContextClassLoader();
      try {
        final Class<?> clazz = Class.forName(callbackClass, true, classLoader);
        final CallbackHandler callbackHandler = (CallbackHandler) clazz.newInstance();
        if (callbackHandler != null) {
          mergedConfiguration = mergedConfiguration.useCallbackHandler(callbackHandler);
        }
      } catch (ClassNotFoundException e) {
        throw Messages.log.failedToLoadCallbackHandlerClass(e, callbackClass);
      } catch (Exception e) {
        throw Messages.log.failedToInstantiateCallbackHandlerInstance(e, callbackClass);
      }
    } else if (userName != null) {
      if (password != null && passwordBase64 != null) {
        throw Messages.log.plainTextAndBase64PasswordSpecified();
      }
      final String decodedPassword =
          passwordBase64 != null
              ? CodePointIterator.ofString(passwordBase64)
                  .base64Decode()
                  .asUtf8String()
                  .drainToString()
              : password;
      mergedConfiguration =
          mergedConfiguration.useName(userName).usePassword(decodedPassword).useRealm(realm);
    }
    final AuthenticationContext context =
        AuthenticationContext.empty().with(MatchRule.ALL, mergedConfiguration);

    if (useSeparateConnection) {
      // create a brand new connection - if there is authentication info in the env, use it
      final Connection connection;
      try {
        connection = endpoint.connect(providerUri, OptionMap.EMPTY, context).get();
      } catch (IOException e) {
        throw Messages.log.connectFailed(e);
      }
      final RemoteNamingProvider provider = new RemoteNamingProvider(connection, context, env);
      connection.getAttachments().attach(PROVIDER_KEY, provider);
      return provider;
    } else if (env.containsKey(CONNECTION)) {
      final Connection connection = (Connection) env.get(CONNECTION);
      final RemoteNamingProvider provider = new RemoteNamingProvider(connection, context, env);
      connection.getAttachments().attach(PROVIDER_KEY, provider);
      return provider;
    } else {
      final Attachments attachments = endpoint.getAttachments();
      ProviderMap map = attachments.getAttachment(PROVIDER_MAP_KEY);
      if (map == null) {
        ProviderMap appearing =
            attachments.attachIfAbsent(PROVIDER_MAP_KEY, map = new ProviderMap());
        if (appearing != null) {
          map = appearing;
        }
      }
      final URIKey key =
          new URIKey(
              providerUri.getScheme(),
              providerUri.getUserInfo(),
              providerUri.getHost(),
              providerUri.getPort());
      RemoteNamingProvider provider = map.get(key);
      if (provider == null) {
        RemoteNamingProvider appearing =
            map.putIfAbsent(
                key, provider = new RemoteNamingProvider(endpoint, providerUri, context, env));
        if (appearing != null) {
          provider = appearing;
        }
      }
      return provider;
    }
  }