public static void main()

in modules/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java [207:517]


    public static void main(String[] args) throws Exception {
        log.info("Starting Apache Ignite Web Console Agent...");

        final AgentConfiguration cfg = new AgentConfiguration();

        JCommander jCommander = new JCommander(cfg);

        String osName = System.getProperty("os.name").toLowerCase();

        jCommander.setProgramName("ignite-web-agent." + (osName.contains("win") ? "bat" : "sh"));

        try {
            jCommander.parse(args);
        }
        catch (ParameterException pe) {
            log.error("Failed to parse command line parameters: " + Arrays.toString(args), pe);

            jCommander.usage();

            return;
        }

        String prop = cfg.configPath();

        AgentConfiguration propCfg = new AgentConfiguration();

        try {
            File f = AgentUtils.resolvePath(prop);

            if (f == null)
                log.warn("Failed to find agent property file: {}", prop);
            else
                propCfg.load(f.toURI().toURL());
        }
        catch (IOException e) {
            if (!AgentConfiguration.DFLT_CFG_PATH.equals(prop))
                log.warn("Failed to load agent property file: " + prop, e);
        }

        cfg.merge(propCfg);

        if (cfg.help()) {
            jCommander.usage();

            return;
        }

        System.out.println();
        System.out.println("Agent configuration:");
        System.out.println(cfg);
        System.out.println();

        URI uri;

        try {
            uri = new URI(cfg.serverUri());
        }
        catch (URISyntaxException e) {
            log.error("Failed to parse Ignite Web Console uri", e);

            return;
        }

        if (cfg.tokens() == null) {
            System.out.println("Security token is required to establish connection to the web console.");
            System.out.println(String.format("It is available on the Profile page: https://%s/profile", uri.getHost()));

            String tokens = String.valueOf(readPassword("Enter security tokens separated by comma: "));

            cfg.tokens(new ArrayList<>(Arrays.asList(tokens.trim().split(","))));
        }

        // Create proxy authenticator using passed properties.
        switch (uri.getScheme()) {
            case "http":
            case "https":
                final String username = System.getProperty(uri.getScheme() + ".proxyUsername");
                final char[] pwd = System.getProperty(uri.getScheme() + ".proxyPassword", "").toCharArray();

                Authenticator.setDefault(new Authenticator() {
                    @Override protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(username, pwd);
                    }
                });

                break;

            default:
                // No-op.
        }

        List<String> nodeURIs = cfg.nodeURIs();

        for (int i = nodeURIs.size() - 1; i >= 0; i--) {
            String nodeURI = nodeURIs.get(i);

            try {
                new URI(nodeURI);
            }
            catch (URISyntaxException ignored) {
                log.warn("Failed to parse Ignite node URI: {}.", nodeURI);

                nodeURIs.remove(i);
            }
        }

        if (nodeURIs.isEmpty()) {
            log.error("Failed to find valid URIs for connect to Ignite node via REST. Please check agent settings");

            return;
        }

        boolean serverTrustAll = Boolean.getBoolean("trust.all");
        boolean hasServerTrustStore = cfg.serverTrustStore() != null;

        if (serverTrustAll && hasServerTrustStore) {
            log.warn("Options contains both '--server-trust-store' and '-Dtrust.all=true'. " +
                "Option '-Dtrust.all=true' will be ignored on connect to Web server.");

            serverTrustAll = false;
        }

        boolean nodeTrustAll = Boolean.getBoolean("trust.all");
        boolean hasNodeTrustStore = cfg.nodeTrustStore() != null;

        if (nodeTrustAll && hasNodeTrustStore) {
            log.warn("Options contains both '--node-trust-store' and '-Dtrust.all=true'. " +
                "Option '-Dtrust.all=true' will be ignored on connect to cluster.");

            nodeTrustAll = false;
        }

        cfg.nodeURIs(nodeURIs);

        IO.Options opts = new IO.Options();
        opts.path = "/agents";

        List<String> cipherSuites = cfg.cipherSuites();

        OkHttpClient.Builder builder = new OkHttpClient.Builder()
            .proxyAuthenticator(new ProxyAuthenticator());

        if (
            serverTrustAll ||
            hasServerTrustStore ||
            cfg.serverKeyStore() != null
        ) {
            X509TrustManager serverTrustMgr = trustManager(
                serverTrustAll,
                cfg.serverTrustStore(),
                cfg.serverTrustStorePassword()
            );

            if (serverTrustAll)
                builder.hostnameVerifier((hostname, session) -> true);

            SSLSocketFactory sslSocketFactory = sslSocketFactory(
                cfg.serverKeyStore(),
                cfg.serverKeyStorePassword(),
                serverTrustMgr,
                cipherSuites
            );

            if (sslSocketFactory != null) {
                if (serverTrustMgr != null)
                    builder.sslSocketFactory(sslSocketFactory, serverTrustMgr);
                else
                    builder.sslSocketFactory(sslSocketFactory);

                if (!F.isEmpty(cipherSuites))
                    builder.connectionSpecs(sslConnectionSpec(cipherSuites));
            }

            opts.secure = true;
        }

        OkHttpClient okHttpClient = builder.build();
        
        opts.callFactory = okHttpClient;
        opts.webSocketFactory = okHttpClient;

        final Socket client = IO.socket(uri, opts);

        try (
            RestExecutor restExecutor = new RestExecutor(
                nodeTrustAll,
                cfg.nodeKeyStore(), cfg.nodeKeyStorePassword(),
                cfg.nodeTrustStore(), cfg.nodeTrustStorePassword(),
                cipherSuites);

            ClusterListener clusterLsnr = new ClusterListener(cfg, client, restExecutor)
        ) {
            Emitter.Listener onConnect = connectRes -> {
                log.info("Connection established.");

                JSONObject authMsg = new JSONObject();

                try {
                    authMsg.put("tokens", toJSON(cfg.tokens()));
                    authMsg.put("disableDemo", cfg.disableDemo());

                    String clsName = AgentLauncher.class.getSimpleName() + ".class";

                    String clsPath = AgentLauncher.class.getResource(clsName).toString();

                    if (clsPath.startsWith("jar")) {
                        String manifestPath = clsPath.substring(0, clsPath.lastIndexOf('!') + 1) +
                            "/META-INF/MANIFEST.MF";

                        Manifest manifest = new Manifest(new URL(manifestPath).openStream());

                        Attributes attr = manifest.getMainAttributes();

                        authMsg.put("ver", attr.getValue("Implementation-Version"));
                        authMsg.put("bt", attr.getValue("Build-Time"));
                    }

                    client.emit("agent:auth", authMsg, (Ack) authRes -> {
                        if (authRes != null) {
                            if (authRes[0] instanceof String) {
                                log.error((String)authRes[0]);

                                System.exit(1);
                            }

                            if (authRes[0] == null && authRes[1] instanceof JSONArray) {
                                try {
                                    List<String> activeTokens = fromJSON(authRes[1], List.class);

                                    if (!F.isEmpty(activeTokens)) {
                                        Collection<String> missedTokens = cfg.tokens();

                                        cfg.tokens(activeTokens);

                                        missedTokens.removeAll(activeTokens);

                                        if (!F.isEmpty(missedTokens)) {
                                            String tokens = F.concat(missedTokens, ", ");

                                            log.warn("Failed to authenticate with token(s): {}. " +
                                                "Please reload agent archive or check settings", tokens);
                                        }

                                        log.info("Authentication success.");

                                        clusterLsnr.watch();

                                        return;
                                    }
                                }
                                catch (Exception e) {
                                    log.error("Failed to authenticate agent. Please check agent\'s tokens", e);

                                    System.exit(1);
                                }
                            }
                        }

                        log.error("Failed to authenticate agent. Please check agent\'s tokens");

                        System.exit(1);
                    });
                }
                catch (JSONException | IOException e) {
                    log.error("Failed to construct authentication message", e);

                    client.close();
                }
            };

            DatabaseListener dbHnd = new DatabaseListener(cfg);

            RestListener restHnd = new RestListener(cfg, restExecutor);

            final CountDownLatch latch = new CountDownLatch(1);

            log.info("Connecting to: {}", cfg.serverUri());

            client
                .on(EVENT_CONNECT, onConnect)
                .on(EVENT_CONNECT_ERROR, onError)
                .on(EVENT_ERROR, onError)
                .on(EVENT_DISCONNECT, onDisconnect)
                .on(EVENT_LOG_WARNING, onLogWarning)
                .on(EVENT_RESET_TOKEN, res -> {
                    String tok = String.valueOf(res[0]);

                    log.warn("Security token has been reset: {}", tok);

                    cfg.tokens().remove(tok);

                    if (cfg.tokens().isEmpty()) {
                        client.off();

                        latch.countDown();
                    }
                })
                .on(EVENT_SCHEMA_IMPORT_DRIVERS, dbHnd.availableDriversListener())
                .on(EVENT_SCHEMA_IMPORT_SCHEMAS, dbHnd.schemasListener())
                .on(EVENT_SCHEMA_IMPORT_METADATA, dbHnd.metadataListener())
                .on(EVENT_NODE_VISOR_TASK, restHnd)
                .on(EVENT_NODE_REST, restHnd);

            client.connect();

            latch.await();
        }
        finally {
            client.close();
        }
    }