public static RemoteWSFrameworkConnectionInfo buildRemoteWSFrameworkConnectionInfo(
     boolean isSecure, int port) {
   return RemoteWSFrameworkConnectionInfo.newBuilder()
       .setRemoteURI(URI.create((isSecure ? "wss" : "ws") + "://127.0.0.1:" + port + "/openicf"))
       .setPrincipal("anonymous")
       .setPassword(DEFAULT_GUARDED_PASSWORD)
       .build();
 }
@Test
public class AsyncRemotePlainConnectorInfoManagerTest
    extends AsyncConnectorInfoManagerTestBase<DelegatingAsyncConnectorInfoManager> {

  public final int PLAIN_PORT = findFreePort();
  public final int SECURE_PORT = findFreePort();
  public final int MUTUAL_SECURE_PORT = findFreePort();

  public final RemoteWSFrameworkConnectionInfo CONNECTION_INFO =
      buildRemoteWSFrameworkConnectionInfo(false, PLAIN_PORT);
  public final RemoteWSFrameworkConnectionInfo SECURE_CONNECTION_INFO =
      buildRemoteWSFrameworkConnectionInfo(true, SECURE_PORT);

  public static final RemoteWSFrameworkConnectionInfo SERVER_CONNECTION_INFO =
      RemoteWSFrameworkConnectionInfo.newBuilder()
          .setRemoteURI(URI.create("ws://127.0.0.1:8759/openicf"))
          .setPrincipal("Something")
          .setPassword(DEFAULT_GUARDED_PASSWORD)
          .build();

  public static RemoteWSFrameworkConnectionInfo buildRemoteWSFrameworkConnectionInfo(
      boolean isSecure, int port) {
    return RemoteWSFrameworkConnectionInfo.newBuilder()
        .setRemoteURI(URI.create((isSecure ? "wss" : "ws") + "://127.0.0.1:" + port + "/openicf"))
        .setPrincipal("anonymous")
        .setPassword(DEFAULT_GUARDED_PASSWORD)
        .build();
  }

  private final ConnectorFrameworkFactory localConnectorFrameworkFactory =
      new ConnectorFrameworkFactory();

  protected static final ConnectorFrameworkFactory serverConnectorFrameworkFactory =
      new ConnectorFrameworkFactory();

  private Server connectorServer = null;
  protected static ReferenceCountedObject<ConnectorFramework>.Reference localConnectorFramework =
      null;
  private static ReferenceCountedObject<ConnectorFramework>.Reference serverConnectorFramework =
      null;

  protected ConnectorFrameworkFactory getConnectorFrameworkFactory() throws Exception {
    return localConnectorFrameworkFactory;
  }

  protected DelegatingAsyncConnectorInfoManager getConnectorInfoManager() throws Exception {
    return getConnectorFramework().getRemoteManager(CONNECTION_INFO);
  }

  private SecurityHandler getSecurityHandler() throws IOException {
    Constraint constraint = new Constraint(Constraint.__BASIC_AUTH, "websocket");
    constraint.setAuthenticate(true);

    ConstraintMapping cm = new ConstraintMapping();
    cm.setPathSpec("/openicf/*");
    cm.setConstraint(constraint);

    ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
    sh.setAuthenticator(new BasicAuthenticator());
    sh.setConstraintMappings(Arrays.asList(new ConstraintMapping[] {cm}));

    MappedLoginService loginService =
        new MappedLoginService() {

          @Override
          protected UserIdentity loadUser(String username) {
            return null;
          }

          @Override
          protected void loadUsers() throws IOException {
            Credential credential = Credential.getCredential(DEFAULT_PASSWORD);
            String[] roles = new String[] {"websocket"};
            putUser("plain", credential, roles);
            putUser("secure", credential, roles);
            putUser("proxy", credential, roles);
            putUser("anonymous", credential, roles);
          }
        };
    loginService.setName("OpenICF-Service");
    sh.setLoginService(loginService);
    sh.setConstraintMappings(Arrays.asList(new ConstraintMapping[] {cm}));

    return sh;
  }

  protected void setupTest(ITestContext context) throws Exception {
    Reporter.log(
        String.format(
            "HTTP:%d, HTTPS:%d , HTTPS(Mutual):%d", PLAIN_PORT, SECURE_PORT, MUTUAL_SECURE_PORT),
        true);

    connectorServer = new Server();

    HttpConfiguration httpConfig = new HttpConfiguration();
    httpConfig.setSecureScheme("https");
    httpConfig.setSecurePort(SECURE_PORT);
    httpConfig.setOutputBufferSize(32768);

    // HTTP
    ServerConnector http =
        new ServerConnector(connectorServer, new HttpConnectionFactory(httpConfig));
    http.setPort(PLAIN_PORT);
    http.setHost("127.0.0.1");
    http.setIdleTimeout(30000);

    // HTTPS
    SslContextFactory sslContextFactory = createSsllContextFactory(false);

    // HTTPS Configuration
    HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
    httpsConfig.addCustomizer(new SecureRequestCustomizer());

    // HTTPS connector
    ServerConnector https =
        new ServerConnector(
            connectorServer,
            new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
            new HttpConnectionFactory(httpsConfig));
    https.setPort(SECURE_PORT);
    http.setHost("127.0.0.1");
    https.setIdleTimeout(500000);

    // Mutual HTTPS connector
    sslContextFactory = createSsllContextFactory(false);
    sslContextFactory.setWantClientAuth(true);
    sslContextFactory.setNeedClientAuth(false);

    ServerConnector mutualHttps =
        new ServerConnector(
            connectorServer,
            new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
            new HttpConnectionFactory(httpsConfig));
    mutualHttps.setPort(MUTUAL_SECURE_PORT);
    http.setHost("127.0.0.1");
    mutualHttps.setIdleTimeout(500000);

    connectorServer.setConnectors(new Connector[] {http, https, mutualHttps});

    // Initializing the security handler
    ServletContextHandler handler =
        new ServletContextHandler(
            connectorServer, "/", ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);

    ServletHolder holder = handler.getServletHandler().newServletHolder(BaseHolder.Source.EMBEDDED);

    serverConnectorFramework = serverConnectorFrameworkFactory.acquire();
    localConnectorFramework = localConnectorFrameworkFactory.acquire();
    holder.setServlet(new OpenICFWebSocketServletBase(serverConnectorFrameworkFactory));
    holder.setInitParameter("maxIdleTime", "300000");
    holder.setInitParameter("maxAsyncWriteTimeout", "60000");

    holder.setInitParameter("maxBinaryMessageSize", "32768");
    holder.setInitParameter("inputBufferSize", "4096");

    handler.addServlet(holder, "/openicf/*");

    SecurityHandler sh = getSecurityHandler();
    sh.setHandler(handler);

    connectorServer.setHandler(sh);
    connectorServer.start();
    Reporter.log("Jetty Server Started", true);

    // Initialise the ConnectorFramework

    serverConnectorFramework
        .get()
        .getLocalManager()
        .addConnectorBundle(TstConnector.class.getProtectionDomain().getCodeSource().getLocation());

    localConnectorFramework
        .get()
        .getLocalManager()
        .addConnectorBundle(TstConnector.class.getProtectionDomain().getCodeSource().getLocation());

    connectorServer.start();
  }

  protected void shutdownTest(ITestContext context) throws Exception {
    connectorServer.stop();
    connectorServer.destroy();

    serverConnectorFramework.release();
    localConnectorFramework.release();
    Reporter.log("Jetty Server Stopped", true);
  }

  private SslContextFactory createSsllContextFactory(boolean clientContext) {
    final SslContextFactory sslContextFactory = new SslContextFactory(false);

    URL keystoreURL =
        AsyncRemotePlainConnectorInfoManagerTest.class
            .getClassLoader()
            .getResource(clientContext ? "clientKeystore.jks" : "serverKeystore.jks");
    Assert.assertNotNull(keystoreURL);
    String serverKeystoreFile = null;
    try {
      serverKeystoreFile = URLDecoder.decode(keystoreURL.getFile(), "UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    URL truststoreURL =
        AsyncRemotePlainConnectorInfoManagerTest.class
            .getClassLoader()
            .getResource("truststore.jks");
    Assert.assertNotNull(truststoreURL);
    String truststoreFile = null;
    try {
      truststoreFile = URLDecoder.decode(truststoreURL.getFile(), "UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    sslContextFactory.setTrustStorePath(truststoreFile);
    sslContextFactory.setTrustStorePassword(JSK_PASSWORD);

    sslContextFactory.setKeyStorePath(serverKeystoreFile);
    sslContextFactory.setKeyStorePassword(JSK_PASSWORD);

    sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.1", "TLSv1");

    return sslContextFactory;
  }

  @Test
  public void testRequiredServerConnectorInfo() throws Exception {
    AsyncConnectorInfoManager manager =
        localConnectorFramework.get().getRemoteManager(CONNECTION_INFO);
    Assert.assertNotNull(manager);

    manager = serverConnectorFramework.get().getServerManager("anonymous");
    Assert.assertNotNull(manager);

    ConnectorInfo c =
        manager
            .findConnectorInfoAsync(getTestConnectorKey())
            .getOrThrowUninterruptibly(5, TimeUnit.MINUTES);
    Assert.assertNotNull(c);

    Assert.assertNotNull(
        manager
            .findConnectorInfoAsync(getTestStatefulConnectorKey())
            .getOrThrowUninterruptibly(30, TimeUnit.SECONDS));

    Assert.assertNotNull(
        manager
            .findConnectorInfoAsync(getTestPoolableStatefulConnectorKey())
            .getOrThrowUninterruptibly(30, TimeUnit.SECONDS));

    for (ConnectorInfo ci : manager.getConnectorInfos()) {
      Reporter.log(String.valueOf(ci.getConnectorKey()), true);
    }
  }
}