UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

191 lines 27.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cfn_fn_1 = require("./cfn-fn"); const token_1 = require("./token"); const util_1 = require("./util"); class Arn { /** * Creates an ARN from components. * * If `partition`, `region` or `account` are not specified, the stack's * partition, region and account will be used. * * If any component is the empty string, an empty string will be inserted * into the generated ARN at the location that component corresponds to. * * The ARN will be formatted as follows: * * arn:{partition}:{service}:{region}:{account}:{resource}{sep}{resource-name} * * The required ARN pieces that are omitted will be taken from the stack that * the 'scope' is attached to. If all ARN pieces are supplied, the supplied scope * can be 'undefined'. */ static format(components, stack) { const partition = components.partition !== undefined ? components.partition : stack.partition; const region = components.region !== undefined ? components.region : stack.region; const account = components.account !== undefined ? components.account : stack.account; const sep = components.sep !== undefined ? components.sep : '/'; const values = ['arn', ':', partition, ':', components.service, ':', region, ':', account, ':', components.resource]; if (sep !== '/' && sep !== ':' && sep !== '') { throw new Error('resourcePathSep may only be ":", "/" or an empty string'); } if (components.resourceName != null) { values.push(sep); values.push(components.resourceName); } return values.join(''); } /** * Given an ARN, parses it and returns components. * * If the ARN is a concrete string, it will be parsed and validated. The * separator (`sep`) will be set to '/' if the 6th component includes a '/', * in which case, `resource` will be set to the value before the '/' and * `resourceName` will be the rest. In case there is no '/', `resource` will * be set to the 6th components and `resourceName` will be set to the rest * of the string. * * If the ARN includes tokens (or is a token), the ARN cannot be validated, * since we don't have the actual value yet at the time of this function * call. You will have to know the separator and the type of ARN. The * resulting `ArnComponents` object will contain tokens for the * subexpressions of the ARN, not string literals. In this case this * function cannot properly parse the complete final resourceName (path) out * of ARNs that use '/' to both separate the 'resource' from the * 'resourceName' AND to subdivide the resourceName further. For example, in * S3 ARNs: * * arn:aws:s3:::my_corporate_bucket/path/to/exampleobject.png * * After parsing the resourceName will not contain * 'path/to/exampleobject.png' but simply 'path'. This is a limitation * because there is no slicing functionality in CloudFormation templates. * * @param arn The ARN to parse * @param sepIfToken The separator used to separate resource from resourceName * @param hasName Whether there is a name component in the ARN at all. For * example, SNS Topics ARNs have the 'resource' component contain the topic * name, and no 'resourceName' component. * * @returns an ArnComponents object which allows access to the various * components of the ARN. * * @returns an ArnComponents object which allows access to the various * components of the ARN. */ static parse(arn, sepIfToken = '/', hasName = true) { if (token_1.Token.isUnresolved(arn)) { return parseToken(arn, sepIfToken, hasName); } const components = arn.split(':'); if (components.length < 6) { throw new Error('ARNs must have at least 6 components: ' + arn); } const [arnPrefix, partition, service, region, account, sixth, ...rest] = components; if (arnPrefix !== 'arn') { throw new Error('ARNs must start with "arn:": ' + arn); } if (!service) { throw new Error('The `service` component (3rd component) is required: ' + arn); } if (!sixth) { throw new Error('The `resource` component (6th component) is required: ' + arn); } let resource; let resourceName; let sep; let sepIndex = sixth.indexOf('/'); if (sepIndex !== -1) { sep = '/'; } else if (rest.length > 0) { sep = ':'; sepIndex = -1; } if (sepIndex !== -1) { resource = sixth.substr(0, sepIndex); resourceName = sixth.substr(sepIndex + 1); } else { resource = sixth; } if (rest.length > 0) { if (!resourceName) { resourceName = ''; } else { resourceName += ':'; } resourceName += rest.join(':'); } // "|| undefined" will cause empty strings to be treated as "undefined". // Optional ARN attributes (e.g. region, account) should return as empty string // if they are provided as such. return util_1.filterUndefined({ service: service || undefined, resource: resource || undefined, partition: partition || undefined, region, account, resourceName, sep }); } constructor() { } } exports.Arn = Arn; /** * Given a Token evaluating to ARN, parses it and returns components. * * The ARN cannot be validated, since we don't have the actual value yet * at the time of this function call. You will have to know the separator * and the type of ARN. * * The resulting `ArnComponents` object will contain tokens for the * subexpressions of the ARN, not string literals. * * WARNING: this function cannot properly parse the complete final * resourceName (path) out of ARNs that use '/' to both separate the * 'resource' from the 'resourceName' AND to subdivide the resourceName * further. For example, in S3 ARNs: * * arn:aws:s3:::my_corporate_bucket/path/to/exampleobject.png * * After parsing the resourceName will not contain 'path/to/exampleobject.png' * but simply 'path'. This is a limitation because there is no slicing * functionality in CloudFormation templates. * * @param arnToken The input token that contains an ARN * @param sep The separator used to separate resource from resourceName * @param hasName Whether there is a name component in the ARN at all. * For example, SNS Topics ARNs have the 'resource' component contain the * topic name, and no 'resourceName' component. * @returns an ArnComponents object which allows access to the various * components of the ARN. */ function parseToken(arnToken, sep = '/', hasName = true) { // Arn ARN looks like: // arn:partition:service:region:account-id:resource // arn:partition:service:region:account-id:resourcetype/resource // arn:partition:service:region:account-id:resourcetype:resource // We need the 'hasName' argument because {Fn::Select}ing a nonexistent field // throws an error. const components = cfn_fn_1.Fn.split(':', arnToken); const partition = cfn_fn_1.Fn.select(1, components).toString(); const service = cfn_fn_1.Fn.select(2, components).toString(); const region = cfn_fn_1.Fn.select(3, components).toString(); const account = cfn_fn_1.Fn.select(4, components).toString(); if (sep === ':') { const resource = cfn_fn_1.Fn.select(5, components).toString(); const resourceName = hasName ? cfn_fn_1.Fn.select(6, components).toString() : undefined; return { partition, service, region, account, resource, resourceName, sep }; } else { const lastComponents = cfn_fn_1.Fn.split(sep, cfn_fn_1.Fn.select(5, components)); const resource = cfn_fn_1.Fn.select(0, lastComponents).toString(); const resourceName = hasName ? cfn_fn_1.Fn.select(1, lastComponents).toString() : undefined; return { partition, service, region, account, resource, resourceName, sep }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYXJuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEscUNBQThCO0FBRTlCLG1DQUFnQztBQUNoQyxpQ0FBeUM7QUF5RHpDLE1BQWEsR0FBRztJQUNkOzs7Ozs7Ozs7Ozs7Ozs7O09BZ0JHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUF5QixFQUFFLEtBQVk7UUFDMUQsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDOUYsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDbEYsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDdEYsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDLEdBQUcsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUVoRSxNQUFNLE1BQU0sR0FBRyxDQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBRSxDQUFDO1FBRXZILElBQUksR0FBRyxLQUFLLEdBQUcsSUFBSSxHQUFHLEtBQUssR0FBRyxJQUFJLEdBQUcsS0FBSyxFQUFFLEVBQUU7WUFDNUMsTUFBTSxJQUFJLEtBQUss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QUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUM7S0FDN0U7U0FBTTtRQUNMLE1BQU0sY0FBYyxHQUFHLFdBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFdBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFFL0QsTUFBTSxRQUFRLEdBQUcsV0FBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsY0FBYyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxXQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBRW5GLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUM3RTtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGbiB9IGZyb20gJy4vY2ZuLWZuJztcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSAnLi9zdGFjayc7XG5pbXBvcnQgeyBUb2tlbiB9IGZyb20gJy4vdG9rZW4nO1xuaW1wb3J0IHsgZmlsdGVyVW5kZWZpbmVkIH0gZnJvbSAnLi91dGlsJztcblxuZXhwb3J0IGludGVyZmFjZSBBcm5Db21wb25lbnRzIHtcbiAgLyoqXG4gICAqIFRoZSBwYXJ0aXRpb24gdGhhdCB0aGUgcmVzb3VyY2UgaXMgaW4uIEZvciBzdGFuZGFyZCBBV1MgcmVnaW9ucywgdGhlXG4gICAqIHBhcnRpdGlvbiBpcyBhd3MuIElmIHlvdSBoYXZlIHJlc291cmNlcyBpbiBvdGhlciBwYXJ0aXRpb25zLCB0aGVcbiAgICogcGFydGl0aW9uIGlzIGF3cy1wYXJ0aXRpb25uYW1lLiBGb3IgZXhhbXBsZSwgdGhlIHBhcnRpdGlvbiBmb3IgcmVzb3VyY2VzXG4gICAqIGluIHRoZSBDaGluYSAoQmVpamluZykgcmVnaW9uIGlzIGF3cy1jbi5cbiAgICpcbiAgICogQGRlZmF1bHQgVGhlIEFXUyBwYXJ0aXRpb24gdGhlIHN0YWNrIGlzIGRlcGxveWVkIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcGFydGl0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VydmljZSBuYW1lc3BhY2UgdGhhdCBpZGVudGlmaWVzIHRoZSBBV1MgcHJvZHVjdCAoZm9yIGV4YW1wbGUsXG4gICAqICdzMycsICdpYW0nLCAnY29kZXBpcGxpbmUnKS5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2U6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJlZ2lvbiB0aGUgcmVzb3VyY2UgcmVzaWRlcyBpbi4gTm90ZSB0aGF0IHRoZSBBUk5zIGZvciBzb21lIHJlc291cmNlc1xuICAgKiBkbyBub3QgcmVxdWlyZSBhIHJlZ2lvbiwgc28gdGhpcyBjb21wb25lbnQgbWlnaHQgYmUgb21pdHRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgVGhlIHJlZ2lvbiB0aGUgc3RhY2sgaXMgZGVwbG95ZWQgdG8uXG4gICAqL1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBJRCBvZiB0aGUgQVdTIGFjY291bnQgdGhhdCBvd25zIHRoZSByZXNvdXJjZSwgd2l0aG91dCB0aGUgaHlwaGVucy5cbiAgICogRm9yIGV4YW1wbGUsIDEyMzQ1Njc4OTAxMi4gTm90ZSB0aGF0IHRoZSBBUk5zIGZvciBzb21lIHJlc291cmNlcyBkb24ndFxuICAgKiByZXF1aXJlIGFuIGFjY291bnQgbnVtYmVyLCBzbyB0aGlzIGNvbXBvbmVudCBtaWdodCBiZSBvbWl0dGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBUaGUgYWNjb3VudCB0aGUgc3RhY2sgaXMgZGVwbG95ZWQgdG8uXG4gICAqL1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSB0eXBlIChlLmcuIFwidGFibGVcIiwgXCJhdXRvU2NhbGluZ0dyb3VwXCIsIFwiY2VydGlmaWNhdGVcIikuXG4gICAqIEZvciBzb21lIHJlc291cmNlIHR5cGVzLCBlLmcuIFMzIGJ1Y2tldHMsIHRoaXMgZmllbGQgZGVmaW5lcyB0aGUgYnVja2V0IG5hbWUuXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTZXBhcmF0b3IgYmV0d2VlbiByZXNvdXJjZSB0eXBlIGFuZCB0aGUgcmVzb3VyY2UuXG4gICAqXG4gICAqIENhbiBiZSBlaXRoZXIgJy8nLCAnOicgb3IgYW4gZW1wdHkgc3RyaW5nLiBXaWxsIG9ubHkgYmUgdXNlZCBpZiByZXNvdXJjZU5hbWUgaXMgZGVmaW5lZC5cbiAgICogQGRlZmF1bHQgJy8nXG4gICAqL1xuICByZWFkb25seSBzZXA/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIG5hbWUgb3IgcGF0aCB3aXRoaW4gdGhlIHJlc291cmNlIChpLmUuIFMzIGJ1Y2tldCBvYmplY3Qga2V5KSBvclxuICAgKiBhIHdpbGRjYXJkIHN1Y2ggYXMgYGBcIipcImBgLiBUaGlzIGlzIHNlcnZpY2UtZGVwZW5kZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VOYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgQXJuIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gQVJOIGZyb20gY29tcG9uZW50cy5cbiAgICpcbiAgICogSWYgYHBhcnRpdGlvbmAsIGByZWdpb25gIG9yIGBhY2NvdW50YCBhcmUgbm90IHNwZWNpZmllZCwgdGhlIHN0YWNrJ3NcbiAgICogcGFydGl0aW9uLCByZWdpb24gYW5kIGFjY291bnQgd2lsbCBiZSB1c2VkLlxuICAgKlxuICAgKiBJZiBhbnkgY29tcG9uZW50IGlzIHRoZSBlbXB0eSBzdHJpbmcsIGFuIGVtcHR5IHN0cmluZyB3aWxsIGJlIGluc2VydGVkXG4gICAqIGludG8gdGhlIGdlbmVyYXRlZCBBUk4gYXQgdGhlIGxvY2F0aW9uIHRoYXQgY29tcG9uZW50IGNvcnJlc3BvbmRzIHRvLlxuICAgKlxuICAgKiBUaGUgQVJOIHdpbGwgYmUgZm9ybWF0dGVkIGFzIGZvbGxvd3M6XG4gICAqXG4gICAqICAgYXJuOntwYXJ0aXRpb259OntzZXJ2aWNlfTp7cmVnaW9ufTp7YWNjb3VudH06e3Jlc291cmNlfXtzZXB9e3Jlc291cmNlLW5hbWV9XG4gICAqXG4gICAqIFRoZSByZXF1aXJlZCBBUk4gcGllY2VzIHRoYXQgYXJlIG9taXR0ZWQgd2lsbCBiZSB0YWtlbiBmcm9tIHRoZSBzdGFjayB0aGF0XG4gICAqIHRoZSAnc2NvcGUnIGlzIGF0dGFjaGVkIHRvLiBJZiBhbGwgQVJOIHBpZWNlcyBhcmUgc3VwcGxpZWQsIHRoZSBzdXBwbGllZCBzY29wZVxuICAgKiBjYW4gYmUgJ3VuZGVmaW5lZCcuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZvcm1hdChjb21wb25lbnRzOiBBcm5Db21wb25lbnRzLCBzdGFjazogU3RhY2spOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhcnRpdGlvbiA9IGNvbXBvbmVudHMucGFydGl0aW9uICE9PSB1bmRlZmluZWQgPyBjb21wb25lbnRzLnBhcnRpdGlvbiA6IHN0YWNrLnBhcnRpdGlvbjtcbiAgICBjb25zdCByZWdpb24gPSBjb21wb25lbnRzLnJlZ2lvbiAhPT0gdW5kZWZpbmVkID8gY29tcG9uZW50cy5yZWdpb24gOiBzdGFjay5yZWdpb247XG4gICAgY29uc3QgYWNjb3VudCA9IGNvbXBvbmVudHMuYWNjb3VudCAhPT0gdW5kZWZpbmVkID8gY29tcG9uZW50cy5hY2NvdW50IDogc3RhY2suYWNjb3VudDtcbiAgICBjb25zdCBzZXAgPSBjb21wb25lbnRzLnNlcCAhPT0gdW5kZWZpbmVkID8gY29tcG9uZW50cy5zZXAgOiAnLyc7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSBbICdhcm4nLCAnOicsIHBhcnRpdGlvbiwgJzonLCBjb21wb25lbnRzLnNlcnZpY2UsICc6JywgcmVnaW9uLCAnOicsIGFjY291bnQsICc6JywgY29tcG9uZW50cy5yZXNvdXJjZSBdO1xuXG4gICAgaWYgKHNlcCAhPT0gJy8nICYmIHNlcCAhPT0gJzonICYmIHNlcCAhPT0gJycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVzb3VyY2VQYXRoU2VwIG1heSBvbmx5IGJlIFwiOlwiLCBcIi9cIiBvciBhbiBlbXB0eSBzdHJpbmcnKTtcbiAgICB9XG5cbiAgICBpZiAoY29tcG9uZW50cy5yZXNvdXJjZU5hbWUgIT0gbnVsbCkge1xuICAgICAgdmFsdWVzLnB1c2goc2VwKTtcbiAgICAgIHZhbHVlcy5wdXNoKGNvbXBvbmVudHMucmVzb3VyY2VOYW1lKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWVzLmpvaW4oJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGFuIEFSTiwgcGFyc2VzIGl0IGFuZCByZXR1cm5zIGNvbXBvbmVudHMuXG4gICAqXG4gICAqIElmIHRoZSBBUk4gaXMgYSBjb25jcmV0ZSBzdHJpbmcsIGl0IHdpbGwgYmUgcGFyc2VkIGFuZCB2YWxpZGF0ZWQuIFRoZVxuICAgKiBzZXBhcmF0b3IgKGBzZXBgKSB3aWxsIGJlIHNldCB0byAnLycgaWYgdGhlIDZ0aCBjb21wb25lbnQgaW5jbHVkZXMgYSAnLycsXG4gICAqIGluIHdoaWNoIGNhc2UsIGByZXNvdXJjZWAgd2lsbCBiZSBzZXQgdG8gdGhlIHZhbHVlIGJlZm9yZSB0aGUgJy8nIGFuZFxuICAgKiBgcmVzb3VyY2VOYW1lYCB3aWxsIGJlIHRoZSByZXN0LiBJbiBjYXNlIHRoZXJlIGlzIG5vICcvJywgYHJlc291cmNlYCB3aWxsXG4gICAqIGJlIHNldCB0byB0aGUgNnRoIGNvbXBvbmVudHMgYW5kIGByZXNvdXJjZU5hbWVgIHdpbGwgYmUgc2V0IHRvIHRoZSByZXN0XG4gICAqIG9mIHRoZSBzdHJpbmcuXG4gICAqXG4gICAqIElmIHRoZSBBUk4gaW5jbHVkZXMgdG9rZW5zIChvciBpcyBhIHRva2VuKSwgdGhlIEFSTiBjYW5ub3QgYmUgdmFsaWRhdGVkLFxuICAgKiBzaW5jZSB3ZSBkb24ndCBoYXZlIHRoZSBhY3R1YWwgdmFsdWUgeWV0IGF0IHRoZSB0aW1lIG9mIHRoaXMgZnVuY3Rpb25cbiAgICogY2FsbC4gWW91IHdpbGwgaGF2ZSB0byBrbm93IHRoZSBzZXBhcmF0b3IgYW5kIHRoZSB0eXBlIG9mIEFSTi4gVGhlXG4gICAqIHJlc3VsdGluZyBgQXJuQ29tcG9uZW50c2Agb2JqZWN0IHdpbGwgY29udGFpbiB0b2tlbnMgZm9yIHRoZVxuICAgKiBzdWJleHByZXNzaW9ucyBvZiB0aGUgQVJOLCBub3Qgc3RyaW5nIGxpdGVyYWxzLiBJbiB0aGlzIGNhc2UgdGhpc1xuICAgKiBmdW5jdGlvbiBjYW5ub3QgcHJvcGVybHkgcGFyc2UgdGhlIGNvbXBsZXRlIGZpbmFsIHJlc291cmNlTmFtZSAocGF0aCkgb3V0XG4gICAqIG9mIEFSTnMgdGhhdCB1c2UgJy8nIHRvIGJvdGggc2VwYXJhdGUgdGhlICdyZXNvdXJjZScgZnJvbSB0aGVcbiAgICogJ3Jlc291cmNlTmFtZScgQU5EIHRvIHN1YmRpdmlkZSB0aGUgcmVzb3VyY2VOYW1lIGZ1cnRoZXIuIEZvciBleGFtcGxlLCBpblxuICAgKiBTMyBBUk5zOlxuICAgKlxuICAgKiAgICBhcm46YXdzOnMzOjo6bXlfY29ycG9yYXRlX2J1Y2tldC9wYXRoL3RvL2V4YW1wbGVvYmplY3QucG5nXG4gICAqXG4gICAqIEFmdGVyIHBhcnNpbmcgdGhlIHJlc291cmNlTmFtZSB3aWxsIG5vdCBjb250YWluXG4gICAqICdwYXRoL3RvL2V4YW1wbGVvYmplY3QucG5nJyBidXQgc2ltcGx5ICdwYXRoJy4gVGhpcyBpcyBhIGxpbWl0YXRpb25cbiAgICogYmVjYXVzZSB0aGVyZSBpcyBubyBzbGljaW5nIGZ1bmN0aW9uYWxpdHkgaW4gQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVzLlxuICAgKlxuICAgKiBAcGFyYW0gYXJuIFRoZSBBUk4gdG8gcGFyc2VcbiAgICogQHBhcmFtIHNlcElmVG9rZW4gVGhlIHNlcGFyYXRvciB1c2VkIHRvIHNlcGFyYXRlIHJlc291cmNlIGZyb20gcmVzb3VyY2VOYW1lXG4gICAqIEBwYXJhbSBoYXNOYW1lIFdoZXRoZXIgdGhlcmUgaXMgYSBuYW1lIGNvbXBvbmVudCBpbiB0aGUgQVJOIGF0IGFsbC4gRm9yXG4gICAqIGV4YW1wbGUsIFNOUyBUb3BpY3MgQVJOcyBoYXZlIHRoZSAncmVzb3VyY2UnIGNvbXBvbmVudCBjb250YWluIHRoZSB0b3BpY1xuICAgKiBuYW1lLCBhbmQgbm8gJ3Jlc291cmNlTmFtZScgY29tcG9uZW50LlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBBcm5Db21wb25lbnRzIG9iamVjdCB3aGljaCBhbGxvd3MgYWNjZXNzIHRvIHRoZSB2YXJpb3VzXG4gICAqIGNvbXBvbmVudHMgb2YgdGhlIEFSTi5cbiAgICpcbiAgICogQHJldHVybnMgYW4gQXJuQ29tcG9uZW50cyBvYmplY3Qgd2hpY2ggYWxsb3dzIGFjY2VzcyB0byB0aGUgdmFyaW91c1xuICAgKiAgICAgIGNvbXBvbmVudHMgb2YgdGhlIEFSTi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcGFyc2UoYXJuOiBzdHJpbmcsIHNlcElmVG9rZW46IHN0cmluZyA9ICcvJywgaGFzTmFtZTogYm9vbGVhbiA9IHRydWUpOiBBcm5Db21wb25lbnRzIHtcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGFybikpIHtcbiAgICAgIHJldHVybiBwYXJzZVRva2VuKGFybiwgc2VwSWZUb2tlbiwgaGFzTmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgY29tcG9uZW50cyA9IGFybi5zcGxpdCgnOicpIGFzIEFycmF5PHN0cmluZyB8IHVuZGVmaW5lZD47XG5cbiAgICBpZiAoY29tcG9uZW50cy5sZW5ndGggPCA2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FSTnMgbXVzdCBoYXZlIGF0IGxlYXN0IDYgY29tcG9uZW50czogJyArIGFybik7XG4gICAgfVxuXG4gICAgY29uc3QgWyBhcm5QcmVmaXgsIHBhcnRpdGlvbiwgc2VydmljZSwgcmVnaW9uLCBhY2NvdW50LCBzaXh0aCwgLi4ucmVzdCBdID0gY29tcG9uZW50cztcblxuICAgIGlmIChhcm5QcmVmaXggIT09ICdhcm4nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FSTnMgbXVzdCBzdGFydCB3aXRoIFwiYXJuOlwiOiAnICsgYXJuKTtcbiAgICB9XG5cbiAgICBpZiAoIXNlcnZpY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGBzZXJ2aWNlYCBjb21wb25lbnQgKDNyZCBjb21wb25lbnQpIGlzIHJlcXVpcmVkOiAnICsgYXJuKTtcbiAgICB9XG5cbiAgICBpZiAoIXNpeHRoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBgcmVzb3VyY2VgIGNvbXBvbmVudCAoNnRoIGNvbXBvbmVudCkgaXMgcmVxdWlyZWQ6ICcgKyBhcm4pO1xuICAgIH1cblxuICAgIGxldCByZXNvdXJjZTogc3RyaW5nO1xuICAgIGxldCByZXNvdXJjZU5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgc2VwOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBsZXQgc2VwSW5kZXggPSBzaXh0aC5pbmRleE9mKCcvJyk7XG4gICAgaWYgKHNlcEluZGV4ICE9PSAtMSkge1xuICAgICAgc2VwID0gJy8nO1xuICAgIH0gZWxzZSBpZiAocmVzdC5sZW5ndGggPiAwKSB7XG4gICAgICBzZXAgPSAnOic7XG4gICAgICBzZXBJbmRleCA9IC0xO1xuICAgIH1cblxuICAgIGlmIChzZXBJbmRleCAhPT0gLTEpIHtcbiAgICAgIHJlc291cmNlID0gc2l4dGguc3Vic3RyKDAsIHNlcEluZGV4KTtcbiAgICAgIHJlc291cmNlTmFtZSA9IHNpeHRoLnN1YnN0cihzZXBJbmRleCArIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXNvdXJjZSA9IHNpeHRoO1xuICAgIH1cblxuICAgIGlmIChyZXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICghcmVzb3VyY2VOYW1lKSB7XG4gICAgICAgIHJlc291cmNlTmFtZSA9ICcnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb3VyY2VOYW1lICs9ICc6JztcbiAgICAgIH1cblxuICAgICAgcmVzb3VyY2VOYW1lICs9IHJlc3Quam9pbignOicpO1xuICAgIH1cblxuICAgIC8vIFwifHwgdW5kZWZpbmVkXCIgd2lsbCBjYXVzZSBlbXB0eSBzdHJpbmdzIHRvIGJlIHRyZWF0ZWQgYXMgXCJ1bmRlZmluZWRcIi5cbiAgICAvLyBPcHRpb25hbCBBUk4gYXR0cmlidXRlcyAoZS5nLiByZWdpb24sIGFjY291bnQpIHNob3VsZCByZXR1cm4gYXMgZW1wdHkgc3RyaW5nXG4gICAgLy8gaWYgdGhleSBhcmUgcHJvdmlkZWQgYXMgc3VjaC5cbiAgICByZXR1cm4gZmlsdGVyVW5kZWZpbmVkKHtcbiAgICAgIHNlcnZpY2U6IHNlcnZpY2UgfHwgdW5kZWZpbmVkLFxuICAgICAgcmVzb3VyY2U6IHJlc291cmNlIHx8IHVuZGVmaW5lZCxcbiAgICAgIHBhcnRpdGlvbjogcGFydGl0aW9uIHx8IHVuZGVmaW5lZCxcbiAgICAgIHJlZ2lvbixcbiAgICAgIGFjY291bnQsXG4gICAgICByZXNvdXJjZU5hbWUsXG4gICAgICBzZXBcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7IH1cbn1cblxuLyoqXG4gKiBHaXZlbiBhIFRva2VuIGV2YWx1YXRpbmcgdG8gQVJOLCBwYXJzZXMgaXQgYW5kIHJldHVybnMgY29tcG9uZW50cy5cbiAqXG4gKiBUaGUgQVJOIGNhbm5vdCBiZSB2YWxpZGF0ZWQsIHNpbmNlIHdlIGRvbid0IGhhdmUgdGhlIGFjdHVhbCB2YWx1ZSB5ZXRcbiAqIGF0IHRoZSB0aW1lIG9mIHRoaXMgZnVuY3Rpb24gY2FsbC4gWW91IHdpbGwgaGF2ZSB0byBrbm93IHRoZSBzZXBhcmF0b3JcbiAqIGFuZCB0aGUgdHlwZSBvZiBBUk4uXG4gKlxuICogVGhlIHJlc3VsdGluZyBgQXJuQ29tcG9uZW50c2Agb2JqZWN0IHdpbGwgY29udGFpbiB0b2tlbnMgZm9yIHRoZVxuICogc3ViZXhwcmVzc2lvbnMgb2YgdGhlIEFSTiwgbm90IHN0cmluZyBsaXRlcmFscy5cbiAqXG4gKiBXQVJOSU5HOiB0aGlzIGZ1bmN0aW9uIGNhbm5vdCBwcm9wZXJseSBwYXJzZSB0aGUgY29tcGxldGUgZmluYWxcbiAqIHJlc291cmNlTmFtZSAocGF0aCkgb3V0IG9mIEFSTnMgdGhhdCB1c2UgJy8nIHRvIGJvdGggc2VwYXJhdGUgdGhlXG4gKiAncmVzb3VyY2UnIGZyb20gdGhlICdyZXNvdXJjZU5hbWUnIEFORCB0byBzdWJkaXZpZGUgdGhlIHJlc291cmNlTmFtZVxuICogZnVydGhlci4gRm9yIGV4YW1wbGUsIGluIFMzIEFSTnM6XG4gKlxuICogICAgYXJuOmF3czpzMzo6Om15X2NvcnBvcmF0ZV9idWNrZXQvcGF0aC90by9leGFtcGxlb2JqZWN0LnBuZ1xuICpcbiAqIEFmdGVyIHBhcnNpbmcgdGhlIHJlc291cmNlTmFtZSB3aWxsIG5vdCBjb250YWluICdwYXRoL3RvL2V4YW1wbGVvYmplY3QucG5nJ1xuICogYnV0IHNpbXBseSAncGF0aCcuIFRoaXMgaXMgYSBsaW1pdGF0aW9uIGJlY2F1c2UgdGhlcmUgaXMgbm8gc2xpY2luZ1xuICogZnVuY3Rpb25hbGl0eSBpbiBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZXMuXG4gKlxuICogQHBhcmFtIGFyblRva2VuIFRoZSBpbnB1dCB0b2tlbiB0aGF0IGNvbnRhaW5zIGFuIEFSTlxuICogQHBhcmFtIHNlcCBUaGUgc2VwYXJhdG9yIHVzZWQgdG8gc2VwYXJhdGUgcmVzb3VyY2UgZnJvbSByZXNvdXJjZU5hbWVcbiAqIEBwYXJhbSBoYXNOYW1lIFdoZXRoZXIgdGhlcmUgaXMgYSBuYW1lIGNvbXBvbmVudCBpbiB0aGUgQVJOIGF0IGFsbC5cbiAqIEZvciBleGFtcGxlLCBTTlMgVG9waWNzIEFSTnMgaGF2ZSB0aGUgJ3Jlc291cmNlJyBjb21wb25lbnQgY29udGFpbiB0aGVcbiAqIHRvcGljIG5hbWUsIGFuZCBubyAncmVzb3VyY2VOYW1lJyBjb21wb25lbnQuXG4gKiBAcmV0dXJucyBhbiBBcm5Db21wb25lbnRzIG9iamVjdCB3aGljaCBhbGxvd3MgYWNjZXNzIHRvIHRoZSB2YXJpb3VzXG4gKiBjb21wb25lbnRzIG9mIHRoZSBBUk4uXG4gKi9cbmZ1bmN0aW9uIHBhcnNlVG9rZW4oYXJuVG9rZW46IHN0cmluZywgc2VwOiBzdHJpbmcgPSAnLycsIGhhc05hbWU6IGJvb2xlYW4gPSB0cnVlKTogQXJuQ29tcG9uZW50cyB7XG4gIC8vIEFybiBBUk4gbG9va3MgbGlrZTpcbiAgLy8gYXJuOnBhcnRpdGlvbjpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50LWlkOnJlc291cmNlXG4gIC8vIGFybjpwYXJ0aXRpb246c2VydmljZTpyZWdpb246YWNjb3VudC1pZDpyZXNvdXJjZXR5cGUvcmVzb3VyY2VcbiAgLy8gYXJuOnBhcnRpdGlvbjpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50LWlkOnJlc291cmNldHlwZTpyZXNvdXJjZVxuXG4gIC8vIFdlIG5lZWQgdGhlICdoYXNOYW1lJyBhcmd1bWVudCBiZWNhdXNlIHtGbjo6U2VsZWN0fWluZyBhIG5vbmV4aXN0ZW50IGZpZWxkXG4gIC8vIHRocm93cyBhbiBlcnJvci5cblxuICBjb25zdCBjb21wb25lbnRzID0gRm4uc3BsaXQoJzonLCBhcm5Ub2tlbik7XG5cbiAgY29uc3QgcGFydGl0aW9uID0gRm4uc2VsZWN0KDEsIGNvbXBvbmVudHMpLnRvU3RyaW5nKCk7XG4gIGNvbnN0IHNlcnZpY2UgPSBGbi5zZWxlY3QoMiwgY29tcG9uZW50cykudG9TdHJpbmcoKTtcbiAgY29uc3QgcmVnaW9uID0gRm4uc2VsZWN0KDMsIGNvbXBvbmVudHMpLnRvU3RyaW5nKCk7XG4gIGNvbnN0IGFjY291bnQgPSBGbi5zZWxlY3QoNCwgY29tcG9uZW50cykudG9TdHJpbmcoKTtcblxuICBpZiAoc2VwID09PSAnOicpIHtcbiAgICBjb25zdCByZXNvdXJjZSA9IEZuLnNlbGVjdCg1LCBjb21wb25lbnRzKS50b1N0cmluZygpO1xuICAgIGNvbnN0IHJlc291cmNlTmFtZSA9IGhhc05hbWUgPyBGbi5zZWxlY3QoNiwgY29tcG9uZW50cykudG9TdHJpbmcoKSA6IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiB7IHBhcnRpdGlvbiwgc2VydmljZSwgcmVnaW9uLCBhY2NvdW50LCByZXNvdXJjZSwgcmVzb3VyY2VOYW1lLCBzZXAgfTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBsYXN0Q29tcG9uZW50cyA9IEZuLnNwbGl0KHNlcCwgRm4uc2VsZWN0KDUsIGNvbXBvbmVudHMpKTtcblxuICAgIGNvbnN0IHJlc291cmNlID0gRm4uc2VsZWN0KDAsIGxhc3RDb21wb25lbnRzKS50b1N0cmluZygpO1xuICAgIGNvbnN0IHJlc291cmNlTmFtZSA9IGhhc05hbWUgPyBGbi5zZWxlY3QoMSwgbGFzdENvbXBvbmVudHMpLnRvU3RyaW5nKCkgOiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4geyBwYXJ0aXRpb24sIHNlcnZpY2UsIHJlZ2lvbiwgYWNjb3VudCwgcmVzb3VyY2UsIHJlc291cmNlTmFtZSwgc2VwIH07XG4gIH1cbn1cbiJdfQ==