UNPKG

@decaf-ts/fabric-weaver

Version:
446 lines 67.4 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FabricCAServerCommandBuilder = void 0;
const logging_1 = require("@decaf-ts/logging");
const fabric_binaries_1 = require("../constants/fabric-binaries.cjs");
const fabric_ca_server_1 = require("../constants/fabric-ca-server.cjs");
const constants_1 = require("../../core/constants/constants.cjs");
const utils_1 = require("../../utils/index.cjs");
const child_process_1 = require("../../utils/child-process.cjs");
class FabricCAServerCommandBuilder {
    constructor(logger) {
        this.binName = fabric_binaries_1.FabricBinaries.SERVER;
        this.command = fabric_ca_server_1.FabricCAServerCommand.HELP;
        this.args = new Map();
        if (!logger)
            this.log = logging_1.Logging.for(FabricCAServerCommandBuilder);
        else
            this.log = logger.for(FabricCAServerCommandBuilder.name);
    }
    /**
     * @description Sets the command for the Fabric CA Server.
     * @summary Configures the primary action for the Fabric CA Server, such as starting the server or generating certificates.
     * @param {FabricCAServerCommand} [command] - The command to be executed by the Fabric CA Server.
     * @return {this} The current instance of the builder for method chaining.
     */
    setCommand(command) {
        if (command !== undefined) {
            this.log.debug(`Setting command: ${command}`);
            this.command = command;
        }
        return this;
    }
    /**
     * @description Sets the port for the Fabric CA Server.
     * @summary Configures the network port on which the Fabric CA Server will listen for incoming connections.
     * @param {number} [port] - The port number for the Fabric CA Server to listen on.
     * @return {this} The current instance of the builder for method chaining.
     */
    setPort(port) {
        if (port !== undefined) {
            this.log.debug(`Setting port: ${port}`);
            this.args.set("port", port);
        }
        return this;
    }
    /**
     * @description Enables or disables debug mode for the Fabric CA Server.
     * @summary Configures whether the Fabric CA Server should run in debug mode, providing more detailed logging and output.
     * @param {boolean} [enable] - Whether to enable debug mode.
     * @return {this} The current instance of the builder for method chaining.
     */
    enableDebug(enable) {
        if (enable !== undefined) {
            this.log.debug(`Setting debug: ${enable}`);
            this.args.set("debug", enable);
        }
        return this;
    }
    setServerTLS(tlsConfig) {
        if (!tlsConfig)
            return this;
        if (tlsConfig.enabled !== undefined) {
            this.log.debug("Setting TLS enabled");
            this.args.set("tls.enabled", tlsConfig.enabled);
        }
        if (tlsConfig.certfile !== undefined) {
            this.log.debug(`Setting TLS cert file: ${tlsConfig.certfile}`);
            this.args.set("tls.certfile", tlsConfig.certfile);
        }
        if (tlsConfig.keyfile !== undefined) {
            this.log.debug(`Setting TLS key file: ${tlsConfig.keyfile}`);
            this.args.set("tls.keyfile", tlsConfig.keyfile);
        }
        if (tlsConfig.clientauth === undefined)
            return this;
        if (tlsConfig.clientauth.certfiles !== undefined) {
            this.log.debug(`Setting TLS client certfiles: ${tlsConfig.clientauth.certfiles}`);
            this.args.set("tls.clientauth.certfiles", tlsConfig.clientauth.certfiles.join(constants_1.COMMA_SEPARATOR));
        }
        if (tlsConfig.clientauth.type !== undefined) {
            this.log.debug(`Setting TLS client auth type: ${tlsConfig.clientauth.type}`);
            this.args.set("tls.clientauth.type", tlsConfig.clientauth.type);
        }
        return this;
    }
    setCA(config) {
        if (!config)
            return this;
        if (config.name !== undefined) {
            this.log.debug(`Setting CA name: ${config.name}`);
            this.args.set("ca.name", config.name);
        }
        if (config.keyfile !== undefined) {
            this.log.debug(`Setting CA key file: ${config.keyfile}`);
            this.args.set("ca.keyfile", config.keyfile);
        }
        if (config.certfile !== undefined) {
            this.log.debug(`Setting CA cert file: ${config.certfile}`);
            this.args.set("ca.certfile", config.certfile);
        }
        if (config.chainfile !== undefined) {
            this.log.debug(`Setting CA chain file: ${config.chainfile}`);
            this.args.set("ca.chainfile", config.chainfile);
        }
        if (config.reenrollIgnoreCertExpiry !== undefined) {
            this.log.debug(`Setting reenrollIgnoreCertExpiry: ${config.reenrollIgnoreCertExpiry}`);
            this.args.set("ca.reenrollignorecertexpiry", config.reenrollIgnoreCertExpiry);
        }
        return this;
    }
    /**
     * @description Sets the address for the Fabric CA Server.
     * @summary Configures the network address on which the Fabric CA Server will listen for incoming connections.
     * @param {string} [address] - The network address for the Fabric CA Server to listen on.
     * @return {this} The current instance of the builder for method chaining.
     */
    setAddress(address) {
        if (address !== undefined) {
            this.log.debug(`Setting address: ${address}`);
            this.args.set("address", address);
        }
        return this;
    }
    /**
     * @description Sets the bootstrap admin user for the Fabric CA Server.
     * @summary Configures the initial admin user with full privileges for the Fabric CA Server.
     * @param {string} [bootUser] - The bootstrap admin user in the format "username:password".
     * @return {this} The current instance of the builder for method chaining.
     */
    setBootstrapAdmin(bootUser) {
        if (bootUser !== undefined) {
            const [user, password] = bootUser.split(":");
            this.log.debug(`Setting bootstrap admin: ${user}:${password}`);
            this.args.set("boot", bootUser);
        }
        return this;
    }
    /**
     * @description Sets the number of CAs to run on the Fabric CA Server.
     * @summary Configures the Fabric CA Server to run multiple CA instances.
     * @param {number} [count] - The number of CA instances to run.
     * @return {this} The current instance of the builder for method chaining.
     */
    setCACount(count) {
        if (count !== undefined) {
            this.log.debug(`Setting CA count: ${count}`);
            this.args.set("cacount", count);
        }
        return this;
    }
    /**
     * @description Sets the configuration files for multiple CAs.
     * @summary Configures the Fabric CA Server with multiple CA configurations using separate files.
     * @param {string[]} [files] - An array of paths to CA configuration files.
     * @return {this} The current instance of the builder for method chaining.
     */
    setCAFiles(files) {
        if (files !== undefined && files.length > 0) {
            this.log.debug(`Setting CA configuration files: ${files.join(", ")}`);
            this.args.set("cafiles", files.join(constants_1.COMMA_SEPARATOR));
        }
        return this;
    }
    setCors(config) {
        if (!config)
            return this;
        if (config.enabled !== undefined) {
            this.log.debug(`Setting CORS enabled: ${config.enabled}`);
            this.args.set("cors.enabled", config.enabled);
        }
        if (config.origins !== undefined) {
            this.log.debug(`Setting CORS origins: ${config.origins.join(", ")}`);
            this.args.set("cors.origins", config.origins.join(constants_1.COMMA_SEPARATOR));
        }
        return this;
    }
    setCrlExpiry(crlExpiry) {
        if (crlExpiry !== undefined) {
            this.log.debug(`Setting CRL expiry: ${crlExpiry}`);
            this.args.set("crl.expiry", crlExpiry);
        }
        return this;
    }
    /**
     * @description Sets the size limit for the Certificate Revocation List (CRL).
     * @summary Configures the maximum number of revoked certificates that can be included in a single CRL.
     * @param {number} [limit] - The maximum number of revoked certificates in the CRL.
     * @return {this} The current instance of the builder for method chaining.
     */
    setCRLSizeLimit(limit) {
        if (limit !== undefined) {
            this.log.debug(`Setting CRL size limit: ${limit}`);
            this.args.set("crlsizelimit", limit);
        }
        return this;
    }
    setCSR(csr) {
        if (csr === undefined)
            return this;
        if (csr.cn !== undefined) {
            this.log.debug(`Setting CSR CN: ${csr.cn}`);
            this.args.set("csr.cn", csr.cn);
        }
        if (csr.hosts !== undefined) {
            this.log.debug(`Setting CSR hosts: ${csr.hosts}`);
            this.args.set("csr.hosts", [...new Set(csr.hosts)].join(constants_1.COMMA_SEPARATOR));
        }
        if (csr.keyrequest !== undefined) {
            if (csr.keyrequest.algo !== undefined) {
                this.log.debug(`Setting CSR key request algorithm: ${csr.keyrequest.algo}`);
                this.args.set("csr.keyrequest.algo", csr.keyrequest.algo);
            }
            if (csr.keyrequest.size !== undefined) {
                this.log.debug(`Setting CSR key request size: ${csr.keyrequest.size}`);
                this.args.set("csr.keyrequest.size", csr.keyrequest.size);
            }
            if (csr.keyrequest.reusekey !== undefined) {
                this.log.debug(`Setting CSR key request reuse key: ${csr.keyrequest.reusekey}`);
                this.args.set("csr.keyrequest.reusekey", csr.keyrequest.reusekey);
            }
        }
        if (csr.serialnumber !== undefined) {
            this.log.debug(`Setting CSR serial number: ${csr.serialnumber}`);
            this.args.set("csr.serialnumber", csr.serialnumber);
        }
        return this;
    }
    setHelp(show) {
        if (show !== undefined) {
            this.log.debug(`Setting help flag: ${show}`);
            this.args.set("help", show);
        }
        return this;
    }
    setHome(home) {
        if (home !== undefined) {
            this.log.debug(`Setting home directory: ${home}`);
            this.args.set("home", home);
        }
        return this;
    }
    setDatabase(cfg) {
        if (cfg === undefined)
            return this;
        if (cfg.type !== undefined) {
            this.log.debug(`Setting database type: ${cfg.type}`);
            this.args.set("db.type", cfg.type);
        }
        if (cfg.datasource !== undefined) {
            this.log.debug(`Setting database datasource: ${cfg.datasource}`);
            this.args.set("db.datasource", cfg.datasource);
        }
        if (cfg.tls !== undefined) {
            if (cfg.tls.certfiles !== undefined) {
                this.log.debug(`Setting TLS certfiles: ${cfg.tls.certfiles}`);
                this.args.set("db.tls.certfiles", cfg.tls.certfiles.join(constants_1.COMMA_SEPARATOR));
            }
            if (cfg.tls.client !== undefined) {
                if (cfg.tls.client.certfile !== undefined) {
                    this.log.debug(`Setting TLS client certfile: ${cfg.tls.client.certfile}`);
                    this.args.set("db.tls.client.certfile", cfg.tls.client.certfile);
                }
                if (cfg.tls.client.keyfile !== undefined) {
                    this.log.debug(`Setting TLS client keyfile: ${cfg.tls.client.keyfile}`);
                    this.args.set("db.tls.client.keyfile", cfg.tls.client.keyfile);
                }
            }
        }
        return this;
    }
    setIdemix(idemix) {
        if (idemix === undefined)
            return this;
        if (idemix.nonceexpiration !== undefined) {
            this.log.debug(`Setting Idemix nonce expiration: ${idemix.nonceexpiration}`);
            this.args.set("idemix.nonceexpiration", idemix.nonceexpiration);
        }
        if (idemix.curve !== undefined) {
            this.log.debug(`Setting Idemix curve: ${idemix.curve}`);
            this.args.set("idemix.curve", idemix.curve);
        }
        if (idemix.noncesweepinterval !== undefined) {
            this.log.debug(`Setting Idemix noncesweep interval: ${idemix.noncesweepinterval}`);
            this.args.set("idemix.noncesweepinterval", idemix.noncesweepinterval);
        }
        if (idemix.rhpoolsize !== undefined) {
            this.log.debug(`Setting Idemix rhpoolsize: ${idemix.rhpoolsize}`);
            this.args.set("idemix.rhpoolsize", idemix.rhpoolsize);
        }
        return this;
    }
    setIntermediate(int) {
        if (int === undefined)
            return this;
        if (int.parentserver !== undefined) {
            if (int.parentserver.url !== undefined) {
                this.log.debug(`Setting intermediate CA parent server URL: ${int.parentserver.url}`);
                this.args.set("intermediate.parentserver.url", int.parentserver.url);
            }
            if (int.parentserver.caname !== undefined) {
                this.log.debug(`Setting intermediate CA parent server caname: ${int.parentserver.caname}`);
                this.args.set("intermediate.parentserver.caname", int.parentserver.caname);
            }
        }
        if (int.enrollment !== undefined) {
            if (int.enrollment.type !== undefined) {
                this.log.debug(`Setting intermediate CA enrollment type: ${int.enrollment.type}`);
                this.args.set("intermediate.enrollment.type", int.enrollment.type);
            }
            if (int.enrollment.profile !== undefined) {
                this.log.debug(`Setting intermediate CA enrollment profile: ${int.enrollment.profile}`);
                this.args.set("intermediate.enrollment.profile", int.enrollment.profile);
            }
            if (int.enrollment.label !== undefined) {
                this.log.debug(`Setting intermediate CA enrollment label: ${int.enrollment.label}`);
                this.args.set("intermediate.enrollment.label", int.enrollment.label);
            }
        }
        if (int.tls !== undefined) {
            if (int.tls.certfiles !== undefined) {
                this.log.debug(`Setting intermediate CA TLS certfiles: ${int.tls.certfiles.join(", ")}`);
                this.args.set("intermediate.tls.certfiles", int.tls.certfiles.join(constants_1.COMMA_SEPARATOR));
            }
            if (int.tls.client !== undefined) {
                if (int.tls.client.certfile !== undefined) {
                    this.log.debug(`Setting intermediate CA TLS client certfile: ${int.tls.client.certfile}`);
                    this.args.set("intermediate.tls.client.certfile", int.tls.client.certfile);
                }
                if (int.tls.client.keyfile !== undefined) {
                    this.log.debug(`Setting intermediate CA TLS client keyfile: ${int.tls.client.keyfile}`);
                    this.args.set("intermediate.tls.client.keyfile", int.tls.client.keyfile);
                }
            }
        }
        return this;
    }
    setLDAP(ldap) {
        if (ldap === undefined)
            return this;
        if (ldap.enabled !== undefined) {
            this.log.debug(`Setting LDAP enabled: ${ldap.enabled}`);
            this.args.set("ldap.enabled", ldap.enabled);
        }
        if (ldap.url !== undefined) {
            this.log.debug(`Setting LDAP URL: ${ldap.url}`);
            this.args.set("ldap.url", ldap.url);
        }
        if (ldap.tls !== undefined) {
            if (ldap.tls.certfiles !== undefined) {
                this.log.debug(`Setting TLS certfiles: ${ldap.tls.certfiles.join(", ")}`);
                this.args.set("ldap.tls.certfiles", ldap.tls.certfiles.join(constants_1.COMMA_SEPARATOR));
            }
            if (ldap.tls.client !== undefined) {
                if (ldap.tls.client.certfile !== undefined) {
                    this.log.debug(`Setting TLS client certfile: ${ldap.tls.client.certfile}`);
                    this.args.set("ldap.tls.client.certfile", ldap.tls.client.certfile);
                }
                if (ldap.tls.client.keyfile !== undefined) {
                    this.log.debug(`Setting TLS client keyfile: ${ldap.tls.client.keyfile}`);
                    this.args.set("ldap.tls.client.keyfile", ldap.tls.client.keyfile);
                }
            }
        }
        if (ldap.attribute !== undefined) {
            if (ldap.attribute.names !== undefined) {
                this.log.debug(`Setting LDAP attribute names: ${ldap.attribute.names.join(", ")}`);
                this.args.set("ldap.attribute.names", ldap.attribute.names.join(constants_1.COMMA_SEPARATOR));
            }
        }
        if (ldap.groupfilter !== undefined) {
            this.log.debug(`Setting LDAP groupfiler: ${ldap.groupfilter}`);
            this.args.set("ldap.groupfilter", ldap.groupfilter);
        }
        if (ldap.userfilter !== undefined) {
            this.log.debug(`Setting LDAP userfilter: ${ldap.userfilter}`);
            this.args.set("ldap.userfilter", ldap.userfilter);
        }
        return this;
    }
    setLogLevel(level) {
        this.log.debug(`Setting log level: ${level}`);
        this.args.set("loglevel", level);
        return this;
    }
    setMaxEnrollments(maxEnrollments) {
        if (maxEnrollments !== undefined) {
            this.log.debug(`Setting max enrollments: ${maxEnrollments}`);
            this.args.set("registry.maxenrollments", maxEnrollments);
        }
        return this;
    }
    setAllowAffiliationsRemove(allow) {
        if (allow !== undefined) {
            this.log.debug(`Setting affiliations allow remove: ${allow}`);
            this.args.set("cfg.affiliations.allowremove", allow);
        }
        return this;
    }
    setAllowIdentitiesRemove(allow) {
        if (allow !== undefined) {
            this.log.debug(`Setting identities allow remove: ${allow}`);
            this.args.set("cfg.identities.allowremove", allow);
        }
        return this;
    }
    setPasswordAttempts(attempts) {
        if (attempts !== undefined) {
            this.log.debug(`Setting password attempts: ${attempts}`);
            this.args.set("cfg.identities.passwordattempts", attempts);
        }
        return this;
    }
    build() {
        const command = [
            this.getBinary(),
            this.getCommand(),
            ...(0, utils_1.mapParser)(this.args),
        ].join(" ");
        this.log.debug(`Built command: ${command}`);
        return command;
    }
    getCommand() {
        return this.command;
    }
    getBinary() {
        return this.binName;
    }
    getArgs() {
        return (0, utils_1.mapParser)(this.args);
    }
    async execute() {
        const bin = this.getBinary();
        const argz = [this.getCommand(), ...this.getArgs()];
        try {
            // const regex = /\[\s*INFO\s*\] Listening on http/;
            // can be used as a promise but to lock the logs running as execsync
            await (0, child_process_1.runCommand)(bin, argz);
        }
        catch (error) {
            this.log.error(`Error: Failed to execute the command: ${error}`);
            process.exit(1);
        }
    }
}
exports.FabricCAServerCommandBuilder = FabricCAServerCommandBuilder;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFicmljLWNhLXNlcnZlci1jb21tYW5kLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZmFicmljL2ZhYnJpYy1jYS1zZXJ2ZXIvZmFicmljLWNhLXNlcnZlci1jb21tYW5kLWJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0NBQW9EO0FBQ3BELGtFQUE4RDtBQUM5RCxvRUFBc0U7QUFXdEUsOERBQWlFO0FBQ2pFLHVDQUF3QztBQUN4Qyw2REFBdUQ7QUFHdkQsTUFBYSw0QkFBNEI7SUFRdkMsWUFBWSxNQUFlO1FBTG5CLFlBQU8sR0FBbUIsZ0NBQWMsQ0FBQyxNQUFNLENBQUM7UUFDaEQsWUFBTyxHQUEwQix3Q0FBcUIsQ0FBQyxJQUFJLENBQUM7UUFFNUQsU0FBSSxHQUFzRCxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRzFFLElBQUksQ0FBQyxNQUFNO1lBQUUsSUFBSSxDQUFDLEdBQUcsR0FBRyxpQkFBTyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDOztZQUM3RCxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsVUFBVSxDQUFDLE9BQStCO1FBQ3hDLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLG9CQUFvQixPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQzlDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE9BQU8sQ0FBQyxJQUFhO1FBQ25CLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGlC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QU0sSUFBQSwwQkFBVSxFQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyx5Q0FBeUMsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNqRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFoa0JELG9FQWdrQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZhYnJpY0JpbmFyaWVzIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtYmluYXJpZXNcIjtcbmltcG9ydCB7IEZhYnJpY0NBU2VydmVyQ29tbWFuZCB9IGZyb20gXCIuLi9jb25zdGFudHMvZmFicmljLWNhLXNlcnZlclwiO1xuaW1wb3J0IHtcbiAgQ0FDb25maWcsXG4gIENvbW1hZENTUkNvbmZpZyxcbiAgQ29tbWFuZEludGVybWVkaWF0ZUNBQ29uZmlnLFxuICBDb21tYW5kTERBUENvbmZpZyxcbiAgQ29yc0NvbmZpZyxcbiAgREJDb25maWcsXG4gIElkZW1peENvbmZpZyxcbiAgU2VydmVyVExTQ29uZmlnLFxufSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9mYWJyaWMvZmFicmljLWNhLXNlcnZlci1jb25maWdcIjtcbmltcG9ydCB7IENPTU1BX1NFUEFSQVRPUiB9IGZyb20gXCIuLi8uLi9jb3JlL2NvbnN0YW50cy9jb25zdGFudHNcIjtcbmltcG9ydCB7IG1hcFBhcnNlciB9IGZyb20gXCIuLi8uLi91dGlsc1wiO1xuaW1wb3J0IHsgcnVuQ29tbWFuZCB9IGZyb20gXCIuLi8uLi91dGlscy9jaGlsZC1wcm9jZXNzXCI7XG5pbXBvcnQgeyBGYWJyaWNMb2dMZXZlbCB9IGZyb20gXCIuLi9jb25zdGFudHMvZmFicmljLWdlbmVyYWxcIjtcblxuZXhwb3J0IGNsYXNzIEZhYnJpY0NBU2VydmVyQ29tbWFuZEJ1aWxkZXIge1xuICBwcml2YXRlIGxvZzogTG9nZ2VyO1xuXG4gIHByaXZhdGUgYmluTmFtZTogRmFicmljQmluYXJpZXMgPSBGYWJyaWNCaW5hcmllcy5TRVJWRVI7XG4gIHByaXZhdGUgY29tbWFuZDogRmFicmljQ0FTZXJ2ZXJDb21tYW5kID0gRmFicmljQ0FTZXJ2ZXJDb21tYW5kLkhFTFA7XG5cbiAgcHJpdmF0ZSBhcmdzOiBNYXA8c3RyaW5nLCBzdHJpbmcgfCBib29sZWFuIHwgbnVtYmVyIHwgc3RyaW5nW10+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbnN0cnVjdG9yKGxvZ2dlcj86IExvZ2dlcikge1xuICAgIGlmICghbG9nZ2VyKSB0aGlzLmxvZyA9IExvZ2dpbmcuZm9yKEZhYnJpY0NBU2VydmVyQ29tbWFuZEJ1aWxkZXIpO1xuICAgIGVsc2UgdGhpcy5sb2cgPSBsb2dnZXIuZm9yKEZhYnJpY0NBU2VydmVyQ29tbWFuZEJ1aWxkZXIubmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGNvbW1hbmQgZm9yIHRoZSBGYWJyaWMgQ0EgU2VydmVyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBwcmltYXJ5IGFjdGlvbiBmb3IgdGhlIEZhYnJpYyBDQSBTZXJ2ZXIsIHN1Y2ggYXMgc3RhcnRpbmcgdGhlIHNlcnZlciBvciBnZW5lcmF0aW5nIGNlcnRpZmljYXRlcy5cbiAgICogQHBhcmFtIHtGYWJyaWNDQVNlcnZlckNvbW1hbmR9IFtjb21tYW5kXSAtIFRoZSBjb21tYW5kIHRvIGJlIGV4ZWN1dGVkIGJ5IHRoZSBGYWJyaWMgQ0EgU2VydmVyLlxuICAgKiBAcmV0dXJuIHt0aGlzfSBUaGUgY3VycmVudCBpbnN0YW5jZSBvZiB0aGUgYnVpbGRlciBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Q29tbWFuZChjb21tYW5kPzogRmFicmljQ0FTZXJ2ZXJDb21tYW5kKTogdGhpcyB7XG4gICAgaWYgKGNvbW1hbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgY29tbWFuZDogJHtjb21tYW5kfWApO1xuICAgICAgdGhpcy5jb21tYW5kID0gY29tbWFuZDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHBvcnQgZm9yIHRoZSBGYWJyaWMgQ0EgU2VydmVyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBuZXR3b3JrIHBvcnQgb24gd2hpY2ggdGhlIEZhYnJpYyBDQSBTZXJ2ZXIgd2lsbCBsaXN0ZW4gZm9yIGluY29taW5nIGNvbm5lY3Rpb25zLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW3BvcnRdIC0gVGhlIHBvcnQgbnVtYmVyIGZvciB0aGUgRmFicmljIENBIFNlcnZlciB0byBsaXN0ZW4gb24uXG4gICAqIEByZXR1cm4ge3RoaXN9IFRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoZSBidWlsZGVyIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRQb3J0KHBvcnQ/OiBudW1iZXIpOiB0aGlzIHtcbiAgICBpZiAocG9ydCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBwb3J0OiAke3BvcnR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwicG9ydFwiLCBwb3J0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVuYWJsZXMgb3IgZGlzYWJsZXMgZGVidWcgbW9kZSBmb3IgdGhlIEZhYnJpYyBDQSBTZXJ2ZXIuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgd2hldGhlciB0aGUgRmFicmljIENBIFNlcnZlciBzaG91bGQgcnVuIGluIGRlYnVnIG1vZGUsIHByb3ZpZGluZyBtb3JlIGRldGFpbGVkIGxvZ2dpbmcgYW5kIG91dHB1dC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZW5hYmxlXSAtIFdoZXRoZXIgdG8gZW5hYmxlIGRlYnVnIG1vZGUuXG4gICAqIEByZXR1cm4ge3RoaXN9IFRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoZSBidWlsZGVyIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBlbmFibGVEZWJ1ZyhlbmFibGU/OiBib29sZWFuKTogdGhpcyB7XG4gICAgaWYgKGVuYWJsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBkZWJ1ZzogJHtlbmFibGV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZGVidWdcIiwgZW5hYmxlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRTZXJ2ZXJUTFModGxzQ29uZmlnPzogU2VydmVyVExTQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKCF0bHNDb25maWcpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHRsc0NvbmZpZy5lbmFibGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFwiU2V0dGluZyBUTFMgZW5hYmxlZFwiKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuZW5hYmxlZFwiLCB0bHNDb25maWcuZW5hYmxlZCk7XG4gICAgfVxuXG4gICAgaWYgKHRsc0NvbmZpZy5jZXJ0ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBUTFMgY2VydCBmaWxlOiAke3Rsc0NvbmZpZy5jZXJ0ZmlsZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2VydGZpbGVcIiwgdGxzQ29uZmlnLmNlcnRmaWxlKTtcbiAgICB9XG5cbiAgICBpZiAodGxzQ29uZmlnLmtleWZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgVExTIGtleSBmaWxlOiAke3Rsc0NvbmZpZy5rZXlmaWxlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInRscy5rZXlmaWxlXCIsIHRsc0NvbmZpZy5rZXlmaWxlKTtcbiAgICB9XG5cbiAgICBpZiAodGxzQ29uZmlnLmNsaWVudGF1dGggPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAodGxzQ29uZmlnLmNsaWVudGF1dGguY2VydGZpbGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBUTFMgY2xpZW50IGNlcnRmaWxlczogJHt0bHNDb25maWcuY2xpZW50YXV0aC5jZXJ0ZmlsZXN9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXG4gICAgICAgIFwidGxzLmNsaWVudGF1dGguY2VydGZpbGVzXCIsXG4gICAgICAgIHRsc0NvbmZpZy5jbGllbnRhdXRoLmNlcnRmaWxlcy5qb2luKENPTU1BX1NFUEFSQVRPUilcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHRsc0NvbmZpZy5jbGllbnRhdXRoLnR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICAgIGBTZXR0aW5nIFRMUyBjbGllbnQgYXV0aCB0eXBlOiAke3Rsc0NvbmZpZy5jbGllbnRhdXRoLnR5cGV9YFxuICAgICAgKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJ0bHMuY2xpZW50YXV0aC50eXBlXCIsIHRsc0NvbmZpZy5jbGllbnRhdXRoLnR5cGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q0EoY29uZmlnOiBDQUNvbmZpZyk6IHRoaXMge1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChjb25maWcubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDQSBuYW1lOiAke2NvbmZpZy5uYW1lfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNhLm5hbWVcIiwgY29uZmlnLm5hbWUpO1xuICAgIH1cblxuICAgIGlmIChjb25maWcua2V5ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDQSBrZXkgZmlsZTogJHtjb25maWcua2V5ZmlsZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJjYS5rZXlmaWxlXCIsIGNvbmZpZy5rZXlmaWxlKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmNlcnRmaWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENBIGNlcnQgZmlsZTogJHtjb25maWcuY2VydGZpbGV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY2EuY2VydGZpbGVcIiwgY29uZmlnLmNlcnRmaWxlKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmNoYWluZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDQSBjaGFpbiBmaWxlOiAke2NvbmZpZy5jaGFpbmZpbGV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY2EuY2hhaW5maWxlXCIsIGNvbmZpZy5jaGFpbmZpbGUpO1xuICAgIH1cblxuICAgIGlmIChjb25maWcucmVlbnJvbGxJZ25vcmVDZXJ0RXhwaXJ5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyByZWVucm9sbElnbm9yZUNlcnRFeHBpcnk6ICR7Y29uZmlnLnJlZW5yb2xsSWdub3JlQ2VydEV4cGlyeX1gXG4gICAgICApO1xuICAgICAgdGhpcy5hcmdzLnNldChcbiAgICAgICAgXCJjYS5yZWVucm9sbGlnbm9yZWNlcnRleHBpcnlcIixcbiAgICAgICAgY29uZmlnLnJlZW5yb2xsSWdub3JlQ2VydEV4cGlyeVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgYWRkcmVzcyBmb3IgdGhlIEZhYnJpYyBDQSBTZXJ2ZXIuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIG5ldHdvcmsgYWRkcmVzcyBvbiB3aGljaCB0aGUgRmFicmljIENBIFNlcnZlciB3aWxsIGxpc3RlbiBmb3IgaW5jb21pbmcgY29ubmVjdGlvbnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWRkcmVzc10gLSBUaGUgbmV0d29yayBhZGRyZXNzIGZvciB0aGUgRmFicmljIENBIFNlcnZlciB0byBsaXN0ZW4gb24uXG4gICAqIEByZXR1cm4ge3RoaXN9IFRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoZSBidWlsZGVyIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRBZGRyZXNzKGFkZHJlc3M/OiBzdHJpbmcpOiB0aGlzIHtcbiAgICBpZiAoYWRkcmVzcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBhZGRyZXNzOiAke2FkZHJlc3N9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiYWRkcmVzc1wiLCBhZGRyZXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGJvb3RzdHJhcCBhZG1pbiB1c2VyIGZvciB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgaW5pdGlhbCBhZG1pbiB1c2VyIHdpdGggZnVsbCBwcml2aWxlZ2VzIGZvciB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtib290VXNlcl0gLSBUaGUgYm9vdHN0cmFwIGFkbWluIHVzZXIgaW4gdGhlIGZvcm1hdCBcInVzZXJuYW1lOnBhc3N3b3JkXCIuXG4gICAqIEByZXR1cm4ge3RoaXN9IFRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoZSBidWlsZGVyIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRCb290c3RyYXBBZG1pbihib290VXNlcj86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChib290VXNlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBbdXNlciwgcGFzc3dvcmRdID0gYm9vdFVzZXIuc3BsaXQoXCI6XCIpO1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgYm9vdHN0cmFwIGFkbWluOiAke3VzZXJ9OiR7cGFzc3dvcmR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiYm9vdFwiLCBib290VXNlcik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBudW1iZXIgb2YgQ0FzIHRvIHJ1biBvbiB0aGUgRmFicmljIENBIFNlcnZlci5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgRmFicmljIENBIFNlcnZlciB0byBydW4gbXVsdGlwbGUgQ0EgaW5zdGFuY2VzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2NvdW50XSAtIFRoZSBudW1iZXIgb2YgQ0EgaW5zdGFuY2VzIHRvIHJ1bi5cbiAgICogQHJldHVybiB7dGhpc30gVGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhlIGJ1aWxkZXIgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldENBQ291bnQoY291bnQ/OiBudW1iZXIpOiB0aGlzIHtcbiAgICBpZiAoY291bnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ0EgY291bnQ6ICR7Y291bnR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY2Fjb3VudFwiLCBjb3VudCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjb25maWd1cmF0aW9uIGZpbGVzIGZvciBtdWx0aXBsZSBDQXMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIEZhYnJpYyBDQSBTZXJ2ZXIgd2l0aCBtdWx0aXBsZSBDQSBjb25maWd1cmF0aW9ucyB1c2luZyBzZXBhcmF0ZSBmaWxlcy5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW2ZpbGVzXSAtIEFuIGFycmF5IG9mIHBhdGhzIHRvIENBIGNvbmZpZ3VyYXRpb24gZmlsZXMuXG4gICAqIEByZXR1cm4ge3RoaXN9IFRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoZSBidWlsZGVyIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRDQUZpbGVzKGZpbGVzPzogc3RyaW5nW10pOiB0aGlzIHtcbiAgICBpZiAoZmlsZXMgIT09IHVuZGVmaW5lZCAmJiBmaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDQSBjb25maWd1cmF0aW9uIGZpbGVzOiAke2ZpbGVzLmpvaW4oXCIsIFwiKX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJjYWZpbGVzXCIsIGZpbGVzLmpvaW4oQ09NTUFfU0VQQVJBVE9SKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q29ycyhjb25maWc/OiBDb3JzQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKCFjb25maWcpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKGNvbmZpZy5lbmFibGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENPUlMgZW5hYmxlZDogJHtjb25maWcuZW5hYmxlZH1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJjb3JzLmVuYWJsZWRcIiwgY29uZmlnLmVuYWJsZWQpO1xuICAgIH1cblxuICAgIGlmIChjb25maWcub3JpZ2lucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDT1JTIG9yaWdpbnM6ICR7Y29uZmlnLm9yaWdpbnMuam9pbihcIiwgXCIpfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNvcnMub3JpZ2luc1wiLCBjb25maWcub3JpZ2lucy5qb2luKENPTU1BX1NFUEFSQVRPUikpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q3JsRXhwaXJ5KGNybEV4cGlyeT86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChjcmxFeHBpcnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgQ1JMIGV4cGlyeTogJHtjcmxFeHBpcnl9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3JsLmV4cGlyeVwiLCBjcmxFeHBpcnkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc2l6ZSBsaW1pdCBmb3IgdGhlIENlcnRpZmljYXRlIFJldm9jYXRpb24gTGlzdCAoQ1JMKS5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgbWF4aW11bSBudW1iZXIgb2YgcmV2b2tlZCBjZXJ0aWZpY2F0ZXMgdGhhdCBjYW4gYmUgaW5jbHVkZWQgaW4gYSBzaW5nbGUgQ1JMLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2xpbWl0XSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiByZXZva2VkIGNlcnRpZmljYXRlcyBpbiB0aGUgQ1JMLlxuICAgKiBAcmV0dXJuIHt0aGlzfSBUaGUgY3VycmVudCBpbnN0YW5jZSBvZiB0aGUgYnVpbGRlciBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Q1JMU2l6ZUxpbWl0KGxpbWl0PzogbnVtYmVyKTogdGhpcyB7XG4gICAgaWYgKGxpbWl0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENSTCBzaXplIGxpbWl0OiAke2xpbWl0fWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNybHNpemVsaW1pdFwiLCBsaW1pdCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q1NSKGNzcj86IENvbW1hZENTUkNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChjc3IgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAoY3NyLmNuICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENTUiBDTjogJHtjc3IuY259YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmNuXCIsIGNzci5jbik7XG4gICAgfVxuXG4gICAgaWYgKGNzci5ob3N0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1IgaG9zdHM6ICR7Y3NyLmhvc3RzfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNzci5ob3N0c1wiLCBbLi4ubmV3IFNldChjc3IuaG9zdHMpXS5qb2luKENPTU1BX1NFUEFSQVRPUikpO1xuICAgIH1cblxuICAgIGlmIChjc3Iua2V5cmVxdWVzdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY3NyLmtleXJlcXVlc3QuYWxnbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCBhbGdvcml0aG06ICR7Y3NyLmtleXJlcXVlc3QuYWxnb31gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJjc3Iua2V5cmVxdWVzdC5hbGdvXCIsIGNzci5rZXlyZXF1ZXN0LmFsZ28pO1xuICAgICAgfVxuICAgICAgaWYgKGNzci5rZXlyZXF1ZXN0LnNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBDU1Iga2V5IHJlcXVlc3Qgc2l6ZTogJHtjc3Iua2V5cmVxdWVzdC5zaXplfWApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3Quc2l6ZVwiLCBjc3Iua2V5cmVxdWVzdC5zaXplKTtcbiAgICAgIH1cbiAgICAgIGlmIChjc3Iua2V5cmVxdWVzdC5yZXVzZWtleSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIENTUiBrZXkgcmVxdWVzdCByZXVzZSBrZXk6ICR7Y3NyLmtleXJlcXVlc3QucmV1c2VrZXl9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLmtleXJlcXVlc3QucmV1c2VrZXlcIiwgY3NyLmtleXJlcXVlc3QucmV1c2VrZXkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjc3Iuc2VyaWFsbnVtYmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIENTUiBzZXJpYWwgbnVtYmVyOiAke2Nzci5zZXJpYWxudW1iZXJ9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiY3NyLnNlcmlhbG51bWJlclwiLCBjc3Iuc2VyaWFsbnVtYmVyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEhlbHAoc2hvdz86IGJvb2xlYW4pOiB0aGlzIHtcbiAgICBpZiAoc2hvdyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBoZWxwIGZsYWc6ICR7c2hvd31gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJoZWxwXCIsIHNob3cpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEhvbWUoaG9tZT86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChob21lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGhvbWUgZGlyZWN0b3J5OiAke2hvbWV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaG9tZVwiLCBob21lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXREYXRhYmFzZShjZmc/OiBEQkNvbmZpZyk6IHRoaXMge1xuICAgIGlmIChjZmcgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAoY2ZnLnR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgZGF0YWJhc2UgdHlwZTogJHtjZmcudHlwZX1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJkYi50eXBlXCIsIGNmZy50eXBlKTtcbiAgICB9XG4gICAgaWYgKGNmZy5kYXRhc291cmNlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGRhdGFiYXNlIGRhdGFzb3VyY2U6ICR7Y2ZnLmRhdGFzb3VyY2V9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiZGIuZGF0YXNvdXJjZVwiLCBjZmcuZGF0YXNvdXJjZSk7XG4gICAgfVxuXG4gICAgaWYgKGNmZy50bHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNmZy50bHMuY2VydGZpbGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgVExTIGNlcnRmaWxlczogJHtjZmcudGxzLmNlcnRmaWxlc31gKTtcbiAgICAgICAgdGhpcy5hcmdzLnNldChcbiAgICAgICAgICBcImRiLnRscy5jZXJ0ZmlsZXNcIixcbiAgICAgICAgICBjZmcudGxzLmNlcnRmaWxlcy5qb2luKENPTU1BX1NFUEFSQVRPUilcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNmZy50bHMuY2xpZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGNmZy50bHMuY2xpZW50LmNlcnRmaWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICAgIGBTZXR0aW5nIFRMUyBjbGllbnQgY2VydGZpbGU6ICR7Y2ZnLnRscy5jbGllbnQuY2VydGZpbGV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5hcmdzLnNldChcImRiLnRscy5jbGllbnQuY2VydGZpbGVcIiwgY2ZnLnRscy5jbGllbnQuY2VydGZpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNmZy50bHMuY2xpZW50LmtleWZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgICAgYFNldHRpbmcgVExTIGNsaWVudCBrZXlmaWxlOiAke2NmZy50bHMuY2xpZW50LmtleWZpbGV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5hcmdzLnNldChcImRiLnRscy5jbGllbnQua2V5ZmlsZVwiLCBjZmcudGxzLmNsaWVudC5rZXlmaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SWRlbWl4KGlkZW1peD86IElkZW1peENvbmZpZyk6IHRoaXMge1xuICAgIGlmIChpZGVtaXggPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAoaWRlbWl4Lm5vbmNlZXhwaXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgYFNldHRpbmcgSWRlbWl4IG5vbmNlIGV4cGlyYXRpb246ICR7aWRlbWl4Lm5vbmNlZXhwaXJhdGlvbn1gXG4gICAgICApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImlkZW1peC5ub25jZWV4cGlyYXRpb25cIiwgaWRlbWl4Lm5vbmNlZXhwaXJhdGlvbik7XG4gICAgfVxuXG4gICAgaWYgKGlkZW1peC5jdXJ2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBJZGVtaXggY3VydmU6ICR7aWRlbWl4LmN1cnZlfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImlkZW1peC5jdXJ2ZVwiLCBpZGVtaXguY3VydmUpO1xuICAgIH1cblxuICAgIGlmIChpZGVtaXgubm9uY2Vzd2VlcGludGVydmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICBgU2V0dGluZyBJZGVtaXggbm9uY2Vzd2VlcCBpbnRlcnZhbDogJHtpZGVtaXgubm9uY2Vzd2VlcGludGVydmFsfWBcbiAgICAgICk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWRlbWl4Lm5vbmNlc3dlZXBpbnRlcnZhbFwiLCBpZGVtaXgubm9uY2Vzd2VlcGludGVydmFsKTtcbiAgICB9XG5cbiAgICBpZiAoaWRlbWl4LnJocG9vbHNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgSWRlbWl4IHJocG9vbHNpemU6ICR7aWRlbWl4LnJocG9vbHNpemV9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwiaWRlbWl4LnJocG9vbHNpemVcIiwgaWRlbWl4LnJocG9vbHNpemUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SW50ZXJtZWRpYXRlKGludDogQ29tbWFuZEludGVybWVkaWF0ZUNBQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKGludCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcztcblxuICAgIGlmIChpbnQucGFyZW50c2VydmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChpbnQucGFyZW50c2VydmVyLnVybCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIGludGVybWVkaWF0ZSBDQSBwYXJlbnQgc2VydmVyIFVSTDogJHtpbnQucGFyZW50c2VydmVyLnVybH1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJpbnRlcm1lZGlhdGUucGFyZW50c2VydmVyLnVybFwiLCBpbnQucGFyZW50c2VydmVyLnVybCk7XG4gICAgICB9XG4gICAgICBpZiAoaW50LnBhcmVudHNlcnZlci5jYW5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICBgU2V0dGluZyBpbnRlcm1lZGlhdGUgQ0EgcGFyZW50IHNlcnZlciBjYW5hbWU6ICR7aW50LnBhcmVudHNlcnZlci5jYW5hbWV9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFxuICAgICAgICAgIFwiaW50ZXJtZWRpYXRlLnBhcmVudHNlcnZlci5jYW5hbWVcIixcbiAgICAgICAgICBpbnQucGFyZW50c2VydmVyLmNhbmFtZVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpbnQuZW5yb2xsbWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaW50LmVucm9sbG1lbnQudHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIGludGVybWVkaWF0ZSBDQSBlbnJvbGxtZW50IHR5cGU6ICR7aW50LmVucm9sbG1lbnQudHlwZX1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXCJpbnRlcm1lZGlhdGUuZW5yb2xsbWVudC50eXBlXCIsIGludC5lbnJvbGxtZW50LnR5cGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW50LmVucm9sbG1lbnQucHJvZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIGludGVybWVkaWF0ZSBDQSBlbnJvbGxtZW50IHByb2ZpbGU6ICR7aW50LmVucm9sbG1lbnQucHJvZmlsZX1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXG4gICAgICAgICAgXCJpbnRlcm1lZGlhdGUuZW5yb2xsbWVudC5wcm9maWxlXCIsXG4gICAgICAgICAgaW50LmVucm9sbG1lbnQucHJvZmlsZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGludC5lbnJvbGxtZW50LmxhYmVsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICAgICAgYFNldHRpbmcgaW50ZXJtZWRpYXRlIENBIGVucm9sbG1lbnQgbGFiZWw6ICR7aW50LmVucm9sbG1lbnQubGFiZWx9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFwiaW50ZXJtZWRpYXRlLmVucm9sbG1lbnQubGFiZWxcIiwgaW50LmVucm9sbG1lbnQubGFiZWwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpbnQudGxzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChpbnQudGxzLmNlcnRmaWxlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIGludGVybWVkaWF0ZSBDQSBUTFMgY2VydGZpbGVzOiAke2ludC50bHMuY2VydGZpbGVzLmpvaW4oXG4gICAgICAgICAgICBcIiwgXCJcbiAgICAgICAgICApfWBcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5hcmdzLnNldChcbiAgICAgICAgICBcImludGVybWVkaWF0ZS50bHMuY2VydGZpbGVzXCIsXG4gICAgICAgICAgaW50LnRscy5jZXJ0ZmlsZXMuam9pbihDT01NQV9TRVBBUkFUT1IpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoaW50LnRscy5jbGllbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoaW50LnRscy5jbGllbnQuY2VydGZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgICAgYFNldHRpbmcgaW50ZXJtZWRpYXRlIENBIFRMUyBjbGllbnQgY2VydGZpbGU6ICR7aW50LnRscy5jbGllbnQuY2VydGZpbGV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5hcmdzLnNldChcbiAgICAgICAgICAgIFwiaW50ZXJtZWRpYXRlLnRscy5jbGllbnQuY2VydGZpbGVcIixcbiAgICAgICAgICAgIGludC50bHMuY2xpZW50LmNlcnRmaWxlXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW50LnRscy5jbGllbnQua2V5ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICAgICAgICBgU2V0dGluZyBpbnRlcm1lZGlhdGUgQ0EgVExTIGNsaWVudCBrZXlmaWxlOiAke2ludC50bHMuY2xpZW50LmtleWZpbGV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5hcmdzLnNldChcbiAgICAgICAgICAgIFwiaW50ZXJtZWRpYXRlLnRscy5jbGllbnQua2V5ZmlsZVwiLFxuICAgICAgICAgICAgaW50LnRscy5jbGllbnQua2V5ZmlsZVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldExEQVAobGRhcD86IENvbW1hbmRMREFQQ29uZmlnKTogdGhpcyB7XG4gICAgaWYgKGxkYXAgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGRhcC5lbmFibGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIExEQVAgZW5hYmxlZDogJHtsZGFwLmVuYWJsZWR9YCk7XG4gICAgICB0aGlzLmFyZ3Muc2V0KFwibGRhcC5lbmFibGVkXCIsIGxkYXAuZW5hYmxlZCk7XG4gICAgfVxuXG4gICAgaWYgKGxkYXAudXJsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIExEQVAgVVJMOiAke2xkYXAudXJsfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImxkYXAudXJsXCIsIGxkYXAudXJsKTtcbiAgICB9XG5cbiAgICBpZiAobGRhcC50bHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGxkYXAudGxzLmNlcnRmaWxlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKFxuICAgICAgICAgIGBTZXR0aW5nIFRMUyBjZXJ0ZmlsZXM6ICR7bGRhcC50bHMuY2VydGZpbGVzLmpvaW4oXCIsIFwiKX1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuYXJncy5zZXQoXG4gICAgICAgICAgXCJsZGFwLnRscy5jZXJ0ZmlsZXNcIixcbiAgICAgICAgICBsZGFwLnRscy5jZXJ0ZmlsZXMuam9pbihDT01NQV9TRVBBUkFUT1IpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChsZGFwLnRscy5jbGllbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAobGRhcC50bHMuY2xpZW50LmNlcnRmaWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICAgIGBTZXR0aW5nIFRMUyBjbGllbnQgY2VydGZpbGU6ICR7bGRhcC50bHMuY2xpZW50LmNlcnRmaWxlfWBcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMuYXJncy5zZXQoXCJsZGFwLnRscy5jbGllbnQuY2VydGZpbGVcIiwgbGRhcC50bHMuY2xpZW50LmNlcnRmaWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsZGFwLnRscy5jbGllbnQua2V5ZmlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICAgICAgICBgU2V0dGluZyBUTFMgY2xpZW50IGtleWZpbGU6ICR7bGRhcC50bHMuY2xpZW50LmtleWZpbGV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5hcmdzLnNldChcImxkYXAudGxzLmNsaWVudC5rZXlmaWxlXCIsIGxkYXAudGxzLmNsaWVudC5rZXlmaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChsZGFwLmF0dHJpYnV0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAobGRhcC5hdHRyaWJ1dGUubmFtZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhcbiAgICAgICAgICBgU2V0dGluZyBMREFQIGF0dHJpYnV0ZSBuYW1lczogJHtsZGFwLmF0dHJpYnV0ZS5uYW1lcy5qb2luKFwiLCBcIil9YFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmFyZ3Muc2V0KFxuICAgICAgICAgIFwibGRhcC5hdHRyaWJ1dGUubmFtZXNcIixcbiAgICAgICAgICBsZGFwLmF0dHJpYnV0ZS5uYW1lcy5qb2luKENPTU1BX1NFUEFSQVRPUilcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobGRhcC5ncm91cGZpbHRlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBMREFQIGdyb3VwZmlsZXI6ICR7bGRhcC5ncm91cGZpbHRlcn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJsZGFwLmdyb3VwZmlsdGVyXCIsIGxkYXAuZ3JvdXBmaWx0ZXIpO1xuICAgIH1cblxuICAgIGlmIChsZGFwLnVzZXJmaWx0ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgTERBUCB1c2VyZmlsdGVyOiAke2xkYXAudXNlcmZpbHRlcn1gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJsZGFwLnVzZXJmaWx0ZXJcIiwgbGRhcC51c2VyZmlsdGVyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldExvZ0xldmVsKGxldmVsOiBGYWJyaWNMb2dMZXZlbCk6IHRoaXMge1xuICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGxvZyBsZXZlbDogJHtsZXZlbH1gKTtcbiAgICB0aGlzLmFyZ3Muc2V0KFwibG9nbGV2ZWxcIiwgbGV2ZWwpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TWF4RW5yb2xsbWVudHMobWF4RW5yb2xsbWVudHM/OiBudW1iZXIpOiB0aGlzIHtcbiAgICBpZiAobWF4RW5yb2xsbWVudHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgbWF4IGVucm9sbG1lbnRzOiAke21heEVucm9sbG1lbnRzfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcInJlZ2lzdHJ5Lm1heGVucm9sbG1lbnRzXCIsIG1heEVucm9sbG1lbnRzKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRBbGxvd0FmZmlsaWF0aW9uc1JlbW92ZShhbGxvdz86IGJvb2xlYW4pOiB0aGlzIHtcbiAgICBpZiAoYWxsb3cgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgYWZmaWxpYXRpb25zIGFsbG93IHJlbW92ZTogJHthbGxvd31gKTtcbiAgICAgIHRoaXMuYXJncy5zZXQoXCJjZmcuYWZmaWxpYXRpb25zLmFsbG93cmVtb3ZlXCIsIGFsbG93KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRBbGxvd0lkZW50aXRpZXNSZW1vdmUoYWxsb3c/OiBib29sZWFuKTogdGhpcyB7XG4gICAgaWYgKGFsbG93ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGlkZW50aXRpZXMgYWxsb3cgcmVtb3ZlOiAke2FsbG93fWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNmZy5pZGVudGl0aWVzLmFsbG93cmVtb3ZlXCIsIGFsbG93KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRQYXNzd29yZEF0dGVtcHRzKGF0dGVtcHRzPzogbnVtYmVyKTogdGhpcyB7XG4gICAgaWYgKGF0dGVtcHRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIHBhc3N3b3JkIGF0dGVtcHRzOiAke2F0dGVtcHRzfWApO1xuICAgICAgdGhpcy5hcmdzLnNldChcImNmZy5pZGVudGl0aWVzLnBhc3N3b3JkYXR0ZW1wdHNcIiwgYXR0ZW1wdHMpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGJ1aWxkKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY29tbWFuZDogc3RyaW5nID0gW1xuICAgICAgdGhpcy5nZXRCaW5hcnkoKSxcbiAgICAgIHRoaXMuZ2V0Q29tbWFuZCgpLFxuICAgICAgLi4ubWFwUGFyc2VyKHRoaXMuYXJncyksXG4gICAgXS5qb2luKFwiIFwiKTtcblxuICAgIHRoaXMubG9nLmRlYnVnKGBCdWlsdCBjb21tYW5kOiAke2NvbW1hbmR9YCk7XG4gICAgcmV0dXJuIGNvbW1hbmQ7XG4gIH1cblxuICBnZXRDb21tYW5kKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY29tbWFuZDtcbiAgfVxuXG4gIGdldEJpbmFyeSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmJpbk5hbWU7XG4gIH1cblxuICBnZXRBcmdzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gbWFwUGFyc2VyKHRoaXMuYXJncyk7XG4gIH1cblxuICBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGJpbiA9IHRoaXMuZ2V0QmluYXJ5KCk7XG4gICAgY29uc3QgYXJneiA9IFt0aGlzLmdldENvbW1hbmQoKSwgLi4udGhpcy5nZXRBcmdzKCldO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGNvbnN0IHJlZ2V4ID0gL1xcW1xccypJTkZPXFxzKlxcXSBMaXN0ZW5pbmcgb24gaHR0cC87XG4gICAgICAvLyBjYW4gYmUgdXNlZCBhcyBhIHByb21pc2UgYnV0IHRvIGxvY2sgdGhlIGxvZ3MgcnVubmluZyBhcyBleGVjc3luY1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChiaW4sIGFyZ3opO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICB0aGlzLmxvZy5lcnJvcihgRXJyb3I6IEZhaWxlZCB0byBleGVjdXRlIHRoZSBjb21tYW5kOiAke2Vycm9yfWApO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfVxufVxuIl19