LyogICBDb3B5cmlnaHQgMjAwNCBUaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24KICoKICogICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogICB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiAqICAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiAgIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiAgIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiAgIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKi8KCnBhY2thZ2Ugb3JnLmFwYWNoZS54bWxiZWFucy5pbXBsLnNjaGVtYTsKCmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYVR5cGU7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYVBhcnRpY2xlOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5YbWxFcnJvcjsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuWG1sT2JqZWN0OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFMb2NhbEVsZW1lbnQ7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYUlkZW50aXR5Q29uc3RyYWludDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hQXR0cmlidXRlTW9kZWw7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYUxvY2FsQXR0cmlidXRlOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFHbG9iYWxFbGVtZW50OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5YbWxJRDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuWG1sQW55U2ltcGxlVHlwZTsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuWG1sU3RyaW5nOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5pbXBsLmNvbW1vbi5YbWxFcnJvckNvbnRleHQ7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLmltcGwuY29tbW9uLlhCZWFuRGVidWc7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLmltcGwuY29tbW9uLlFOYW1lSGVscGVyOwoKaW1wb3J0IGphdmF4LnhtbC5uYW1lc3BhY2UuUU5hbWU7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlzOwppbXBvcnQgamF2YS51dGlsLkNvbGxlY3Rpb247CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CmltcG9ydCBqYXZhLm1hdGguQmlnSW50ZWdlcjsKCnB1YmxpYyBjbGFzcyBTdHNjQ2hlY2tlcgp7CiAgICBwdWJsaWMgc3RhdGljIHZvaWQgY2hlY2tBbGwoKQogICAgewogICAgICAgIC8vIHdhbGsgdGhlIHRyZWUgb2YgdHlwZXMKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CgogICAgICAgIExpc3QgYWxsU2VlblR5cGVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIGFsbFNlZW5UeXBlcy5hZGRBbGwoQXJyYXlzLmFzTGlzdChzdGF0ZS5kb2N1bWVudFR5cGVzKCkpKTsKICAgICAgICBhbGxTZWVuVHlwZXMuYWRkQWxsKEFycmF5cy5hc0xpc3Qoc3RhdGUuYXR0cmlidXRlVHlwZXMoKSkpOwogICAgICAgIGFsbFNlZW5UeXBlcy5hZGRBbGwoQXJyYXlzLmFzTGlzdChzdGF0ZS5yZWRlZmluZWRHbG9iYWxUeXBlcygpKSk7CiAgICAgICAgYWxsU2VlblR5cGVzLmFkZEFsbChBcnJheXMuYXNMaXN0KHN0YXRlLmdsb2JhbFR5cGVzKCkpKTsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBhbGxTZWVuVHlwZXMuc2l6ZSgpOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBTY2hlbWFUeXBlIGdUeXBlID0gKFNjaGVtYVR5cGUpYWxsU2VlblR5cGVzLmdldChpKTsKICAgICAgICAgICAgaWYgKCFzdGF0ZS5ub1B2cigpICYmICAvLyBvcHRpb24gdG8gdHVybiBvZmYgcGFydGljbGUgcmVzdHJpY3Rpb24gY2hlY2tpbmcKICAgICAgICAgICAgICAgICFnVHlwZS5pc0RvY3VtZW50VHlwZSgpKSAvLyBEb24ndCBjaGVjayBkb2MgdHlwZXMgZm9yIHJlc3RyaWN0aW9uLiAKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY2hlY2tSZXN0cmljdGlvbigoU2NoZW1hVHlwZUltcGwpZ1R5cGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNoZWNrRmllbGRzKChTY2hlbWFUeXBlSW1wbClnVHlwZSk7CiAgICAgICAgICAgIGFsbFNlZW5UeXBlcy5hZGRBbGwoQXJyYXlzLmFzTGlzdChnVHlwZS5nZXRBbm9ueW1vdXNUeXBlcygpKSk7CiAgICAgICAgfQoKICAgICAgICBjaGVja1N1YnN0aXR1dGlvbkdyb3VwcyhzdGF0ZS5nbG9iYWxFbGVtZW50cygpKTsKICAgIH0KICAgIAogICAgLyoqCiAgICAgKiBUaGUgZm9sbG93aW5nIGNvZGUgY2hlY2tzIHJ1bGUgIzUgb2YgaHR0cDovL3d3dy53My5vcmcvVFIveG1sc2NoZW1hLTEvI2Nvc3MtY3QKICAgICAqIGFzIHdlbGwgYXMgYXR0cmlidXRlICsgZWxlbWVudCBkZWZhdWx0L2ZpeGVkIHZhbGlkaXR5LgogICAgICovCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgY2hlY2tGaWVsZHMoU2NoZW1hVHlwZUltcGwgc1R5cGUpCiAgICB7CiAgICAgICAgaWYgKHNUeXBlLmlzU2ltcGxlVHlwZSgpKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgCiAgICAgICAgWG1sT2JqZWN0IGxvY2F0aW9uID0gc1R5cGUuZ2V0UGFyc2VPYmplY3QoKTsKICAgICAgICAKICAgICAgICBTY2hlbWFBdHRyaWJ1dGVNb2RlbCBzQXR0ck1vZGVsID0gc1R5cGUuZ2V0QXR0cmlidXRlTW9kZWwoKTsKICAgICAgICBpZiAoc0F0dHJNb2RlbCAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgU2NoZW1hTG9jYWxBdHRyaWJ1dGVbXSBzQXR0cnMgID0gc0F0dHJNb2RlbC5nZXRBdHRyaWJ1dGVzKCk7CiAgICAgICAgICAgIFFOYW1lIGlkQXR0ciA9IG51bGw7CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgc0F0dHJzLmxlbmd0aDsgaSsrKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoWG1sSUQudHlwZS5pc0Fzc2lnbmFibGVGcm9tKHNBdHRyc1tpXS5nZXRUeXBlKCkpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChpZEF0dHIgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgaWRBdHRyID0gc0F0dHJzW2ldLmdldE5hbWUoKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQm90aCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGlkQXR0cikgKyAiIGFuZCAiICsgc0F0dHJzW2ldLmdldE5hbWUoKSArICIgYXJlIHhzOklEIGF0dHJpYnV0ZXM7IG9ubHkgb25lIElEIGF0dHJpYnV0ZSBpcyBhbGxvd2VkIG9uIGEgdHlwZS4iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgIGlmIChzQXR0cnNbaV0uZ2V0RGVmYXVsdFRleHQoKSAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIkFuIGF0dHJpYnV0ZSBvZiB0eXBlIHhzOklEIGlzIG5vdCBhbGxvd2VkIHRvIGhhdmUgYSBkZWZhdWx0IG9yIGZpeGVkIGNvbnN0cmFpbnQuIiwgWG1sRXJyb3JDb250ZXh0LkdFTkVSSUNfRVJST1IsIGxvY2F0aW9uKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBTdHJpbmcgdmFsdWVDb25zdHJhaW50ID0gc0F0dHJzW2ldLmdldERlZmF1bHRUZXh0KCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlQ29uc3RyYWludCAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5CiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFhtbEFueVNpbXBsZVR5cGUgdmFsID0gc0F0dHJzW2ldLmdldERlZmF1bHRWYWx1ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWwudmFsaWRhdGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNjaGVtYVByb3BlcnR5SW1wbCBzUHJvcCA9IChTY2hlbWFQcm9wZXJ0eUltcGwpc1R5cGUuZ2V0QXR0cmlidXRlUHJvcGVydHkoc0F0dHJzW2ldLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc1Byb3AgIT0gbnVsbCAmJiBzUHJvcC5nZXREZWZhdWx0VGV4dCgpICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc1Byb3Auc2V0RGVmYXVsdFZhbHVlKG5ldyBYbWxWYWx1ZVJlZih2YWwpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoRXhjZXB0aW9uIGUpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzQXR0cnNbaV0uaXNGaXhlZCgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiVGhlICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoc0F0dHJzW2ldLmdldE5hbWUoKSkgKyAiIGVsZW1lbnQgZml4ZWQgdmFsdWUgJyIgKyB2YWx1ZUNvbnN0cmFpbnQgKyAiJyBpcyBub3QgYSB2YWxpZCB2YWx1ZSBmb3IgIiArIFFOYW1lSGVscGVyLnJlYWRhYmxlKHNBdHRyc1tpXS5nZXRUeXBlKCkpLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiVGhlICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoc0F0dHJzW2ldLmdldE5hbWUoKSkgKyAiIGVsZW1lbnQgZGVmYXVsdCB2YWx1ZSAnIiArIHZhbHVlQ29uc3RyYWludCArICInIGlzIG5vdCBhIHZhbGlkIHZhbHVlIGZvciAiICsgUU5hbWVIZWxwZXIucmVhZGFibGUoc0F0dHJzW2ldLmdldFR5cGUoKSksIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBsb2NhdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgY2hlY2tFbGVtZW50RGVmYXVsdHMoc1R5cGUuZ2V0Q29udGVudE1vZGVsKCksIGxvY2F0aW9uLCBzVHlwZSk7CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgY2hlY2tFbGVtZW50RGVmYXVsdHMoU2NoZW1hUGFydGljbGUgbW9kZWwsIFhtbE9iamVjdCBsb2NhdGlvbiwgU2NoZW1hVHlwZSBwYXJlbnRUeXBlKQogICAgewogICAgICAgIGlmIChtb2RlbCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgc3dpdGNoIChtb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQ0hPSUNFOgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBtb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGNoZWNrRWxlbWVudERlZmF1bHRzKGNoaWxkcmVuW2ldLCBsb2NhdGlvbiwgcGFyZW50VHlwZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgICAgICBTdHJpbmcgdmFsdWVDb25zdHJhaW50ID0gbW9kZWwuZ2V0RGVmYXVsdFRleHQoKTsKICAgICAgICAgICAgICAgIGlmICh2YWx1ZUNvbnN0cmFpbnQgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAobW9kZWwuZ2V0VHlwZSgpLmlzU2ltcGxlVHlwZSgpIHx8IG1vZGVsLmdldFR5cGUoKS5nZXRDb250ZW50VHlwZSgpID09IFNjaGVtYVR5cGUuU0lNUExFX0NPTlRFTlQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB0cnkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgWG1sQW55U2ltcGxlVHlwZSB2YWwgPSBtb2RlbC5nZXREZWZhdWx0VmFsdWUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmFsLnZhbGlkYXRlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTY2hlbWFQcm9wZXJ0eUltcGwgc1Byb3AgPSAoU2NoZW1hUHJvcGVydHlJbXBsKXBhcmVudFR5cGUuZ2V0RWxlbWVudFByb3BlcnR5KG1vZGVsLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc1Byb3AgIT0gbnVsbCAmJiBzUHJvcC5nZXREZWZhdWx0VGV4dCgpICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc1Byb3Auc2V0RGVmYXVsdFZhbHVlKG5ldyBYbWxWYWx1ZVJlZih2YWwpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoRXhjZXB0aW9uIGUpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtb2RlbC5pc0ZpeGVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJUaGUgIiArIFFOYW1lSGVscGVyLnByZXR0eShtb2RlbC5nZXROYW1lKCkpICsgIiBlbGVtZW50IGZpeGVkIHZhbHVlICciICsgdmFsdWVDb25zdHJhaW50ICsgIicgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yICIgKyBRTmFtZUhlbHBlci5yZWFkYWJsZShtb2RlbC5nZXRUeXBlKCkpLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiVGhlICIgKyBRTmFtZUhlbHBlci5wcmV0dHkobW9kZWwuZ2V0TmFtZSgpKSArICIgZWxlbWVudCBkZWZhdWx0IHZhbHVlICciICsgdmFsdWVDb25zdHJhaW50ICsgIicgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yICIgKyBRTmFtZUhlbHBlci5yZWFkYWJsZShtb2RlbC5nZXRUeXBlKCkpLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1vZGVsLmdldFR5cGUoKS5nZXRDb250ZW50VHlwZSgpID09IFNjaGVtYVR5cGUuTUlYRURfQ09OVEVOVCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbW9kZWwuZ2V0VHlwZSgpLmdldENvbnRlbnRNb2RlbCgpLmlzU2tpcHBhYmxlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZyBjb25zdHJhaW50TmFtZSA9IChtb2RlbC5pc0ZpeGVkKCkgPyAiZml4ZWQiIDogImRlZmF1bHQiKTsKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIlRoZSAiICsgUU5hbWVIZWxwZXIucHJldHR5KG1vZGVsLmdldE5hbWUoKSkgKyAiIGVsZW1lbnQgY2Fubm90IGhhdmUgYSAiICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludE5hbWUgKyAiIHZhbHVlICciICsgdmFsdWVDb25zdHJhaW50ICsgIicgYmVjYXVzZSBpdCdzIGNvbnRlbnQgaXMgbWl4ZWQgIiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJidXQgbm90IGVtcHRpYWJsZS4iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRWxlbWVudCBEZWZhdWx0IFZhbGlkIChJbW1lZGlhdGUpOiBjb3MtdmFsaWQtZGVmYXVsdC4yLjIuMgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm8gbmVlZCB0byB2YWxpZGF0ZSB0aGUgdmFsdWU7IHR5cGUgaXMgYSB4czpzdHJpbmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNjaGVtYVByb3BlcnR5SW1wbCBzUHJvcCA9IChTY2hlbWFQcm9wZXJ0eUltcGwpcGFyZW50VHlwZS5nZXRFbGVtZW50UHJvcGVydHkobW9kZWwuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzUHJvcCAhPSBudWxsICYmIHNQcm9wLmdldERlZmF1bHRUZXh0KCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzUHJvcC5zZXREZWZhdWx0VmFsdWUobmV3IFhtbFZhbHVlUmVmKFhtbFN0cmluZy50eXBlLm5ld1ZhbHVlKHZhbHVlQ29uc3RyYWludCkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtb2RlbC5nZXRUeXBlKCkuZ2V0Q29udGVudFR5cGUoKSA9PSBTY2hlbWFUeXBlLkVMRU1FTlRfQ09OVEVOVCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiVGhlICIgKyBRTmFtZUhlbHBlci5wcmV0dHkobW9kZWwuZ2V0TmFtZSgpKSArICIgZWxlbWVudCBjYW5ub3QgaGF2ZSBhIGRlZmF1bHQgdmFsdWUgJyIgKyB2YWx1ZUNvbnN0cmFpbnQgKyAiJyBiZWNhdXNlIGl0cyB0eXBlIGhhcyBlbGVtZW50IGNvbnRlbnQgb25seS4iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtb2RlbC5nZXRUeXBlKCkuZ2V0Q29udGVudFR5cGUoKSA9PSBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIlRoZSAiICsgUU5hbWVIZWxwZXIucHJldHR5KG1vZGVsLmdldE5hbWUoKSkgKyAiIGVsZW1lbnQgY2Fubm90IGhhdmUgYSBkZWZhdWx0IHZhbHVlICciICsgdmFsdWVDb25zdHJhaW50ICsgIicgYmVjYXVzZSBpdHMgdHlwZSBoYXMgZW1wdHkgY29udGVudCBvbmx5LiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBsb2NhdGlvbik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgLy8gbm90aGluZyB0byBkby4KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIAogICAgLyoqCiAgICAgKiBUaGUgZm9sbG93aW5nIGNvZGUgb25seSBjaGVja3MgcnVsZSAjNSBvZiBodHRwOi8vd3d3LnczLm9yZy9UUi94bWxzY2hlbWEtMS8jZGVyaXZhdGlvbi1vay1yZXN0cmljdGlvbgogICAgICogIChFdmVyeXRoaW5nIGVsc2UgY2FuIGFuZCBzaG91bGQgYmUgZG9uZSBpbiBTdHNjUmVzb2x2ZXIsIGJlY2F1c2Ugd2UgY2FuIGdpdmUgbW9yZSBkZXRhaWxlZCBsaW5lICMgaW5mbyB0aGVyZQogICAgICovCiAgICBwdWJsaWMgc3RhdGljIGJvb2xlYW4gY2hlY2tSZXN0cmljdGlvbihTY2hlbWFUeXBlSW1wbCBzVHlwZSkKICAgIHsKICAgICAgICBpZiAoc1R5cGUuZ2V0RGVyaXZhdGlvblR5cGUoKSA9PSBTY2hlbWFUeXBlLkRUX1JFU1RSSUNUSU9OICYmICFzVHlwZS5pc1NpbXBsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIFN0c2NTdGF0ZSBzdGF0ZSA9IFN0c2NTdGF0ZS5nZXQoKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIHdlIGRvbid0IHJlbWVtYmVyIHZlcnkgcHJlY2lzZSBsaW5lIG51bWJlciBpbmZvcm1hdGlvbiwgYnV0IGl0J3MgYmV0dGVyIHRoYW4gbm90aGluLgogICAgICAgICAgICBYbWxPYmplY3QgbG9jYXRpb24gPSBzVHlwZS5nZXRQYXJzZU9iamVjdCgpOwogICAgICAgIAogICAgICAgICAgICBTY2hlbWFUeXBlIGJhc2VUeXBlID0gc1R5cGUuZ2V0QmFzZVR5cGUoKTsKICAgICAgICAgICAgaWYgKGJhc2VUeXBlLmlzU2ltcGxlVHlwZSgpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiVGhlIGJhc2UgdHlwZSBvZiBhIGNvbXBsZXggdHlwZSByZXN0cmljdGlvbiBtdXN0IGJlIGEgY29tcGxleCB0eXBlLiIsIFhtbEVycm9yQ29udGV4dC5JTExFR0FMX1JFU1RSSUNUSU9OLCBsb2NhdGlvbik7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIDUgVGhlIGFwcHJvcHJpYXRlIGNhc2UgYW1vbmcgdGhlIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgICAgIHN3aXRjaCAoc1R5cGUuZ2V0Q29udGVudFR5cGUoKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UOgogICAgICAgICAgICAgICAgICAgIC8vIDUuMSBJZiB0aGUge2NvbnRlbnQgdHlwZX0gb2YgdGhlIGNvbXBsZXggdHlwZSBkZWZpbml0aW9uIGlzIGEgc2ltcGxlIHR5cGUgZGVmaW5pdGlvbiwgdGhlbiBvbmUgb2YgdGhlIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gNS4xLjEgVGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSB7YmFzZSB0eXBlIGRlZmluaXRpb259IG11c3QgYmUgYSBzaW1wbGUgdHlwZSBkZWZpbml0aW9uIG9mIHdoaWNoIHRoZSB7Y29udGVudCB0eXBlfSBpcyBhILd2YWxpZCByZXN0cmljdGlvbrcgYXMgZGVmaW5lZCBpbiBEZXJpdmF0aW9uIFZhbGlkIChSZXN0cmljdGlvbiwgU2ltcGxlKSAopzMuMTQuNikuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0b2RvOiB3ZSBkb24ndCBhbGxvdyB0aGUgY29udGVudCB0eXBlIHRvIGJlIGFuICJvbiB0aGUgc2lkZSIgc2ltcGxlIHR5cGUsIHNvIG5vdGhpbmcgZmFuY3kgdG8gY2hlY2sgaGVyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLk1JWEVEX0NPTlRFTlQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA1LjEuMiBUaGUge2Jhc2UgdHlwZSBkZWZpbml0aW9ufSBtdXN0IGJlIG1peGVkIGFuZCBoYXZlIGEgcGFydGljbGUgd2hpY2ggaXMgt2VtcHRpYWJsZbcgYXMgZGVmaW5lZCBpbiBQYXJ0aWNsZSBFbXB0aWFibGUgKKczLjkuNikuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUuZ2V0Q29udGVudE1vZGVsKCkgIT0gbnVsbCAmJiAhYmFzZVR5cGUuZ2V0Q29udGVudE1vZGVsKCkuaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSB0eXBlIHdpdGggYSBzaW1wbGUgY29udGVudCBtb2RlbCBjYW4gb25seSByZXN0cmljdCBhIG1peGVkIGNvbnRlbnQgbW9kZWwgdGhhdCBoYXMgc2tpcHBhYmxlIGVsZW1lbnRzLiIsIFhtbEVycm9yQ29udGV4dC5JTExFR0FMX1JFU1RSSUNUSU9OLCBsb2NhdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgd2l0aCBhIHNpbXBsZSBjb250ZW50IG1vZGVsIGNhbiBvbmx5IHJlc3RyaWN0IGEgc2ltcGxlIG9yIG1peGVkIGNvbnRlbnQgbW9kZWwuIiwgWG1sRXJyb3JDb250ZXh0LklMTEVHQUxfUkVTVFJJQ1RJT04sIGxvY2F0aW9uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuRU1QVFlfQ09OVEVOVDoKICAgICAgICAgICAgICAgICAgICAvLyA1LjIgSWYgdGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSBjb21wbGV4IHR5cGUgaXRzZWxmIGlzIGVtcHR5ICwgdGhlbiBvbmUgb2YgdGhlIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA1LjIuMSBUaGUge2NvbnRlbnQgdHlwZX0gb2YgdGhlIHtiYXNlIHR5cGUgZGVmaW5pdGlvbn0gbXVzdCBhbHNvIGJlIGVtcHR5LgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuRUxFTUVOVF9DT05URU5UOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gNS4yLjIgVGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSB7YmFzZSB0eXBlIGRlZmluaXRpb259IG11c3QgYmUgZWxlbWVudE9ubHkgb3IgbWl4ZWQgYW5kIGhhdmUgYSBwYXJ0aWNsZSB3aGljaCBpcyC3ZW1wdGlhYmxltyBhcyBkZWZpbmVkIGluIFBhcnRpY2xlIEVtcHRpYWJsZSAopzMuOS42KS4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZS5nZXRDb250ZW50TW9kZWwoKSAhPSBudWxsICYmICFiYXNlVHlwZS5nZXRDb250ZW50TW9kZWwoKS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgd2l0aCBhbiBlbXB0eSBjb250ZW50IG1vZGVsIGNhbiBvbmx5IHJlc3RyaWN0IGEgY29udGVudCBtb2RlbCB0aGF0IGhhcyBza2lwcGFibGUgZWxlbWVudHMuIiwgWG1sRXJyb3JDb250ZXh0LklMTEVHQUxfUkVTVFJJQ1RJT04sIGxvY2F0aW9uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDogICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSB0eXBlIHdpdGggYW4gZW1wdHkgY29udGVudCBtb2RlbCBjYW5ub3QgcmVzdHJpY3QgYSB0eXBlIHdpdGggYSBzaW1wbGUgY29udGVudCBtb2RlbC4iLCBYbWxFcnJvckNvbnRleHQuSUxMRUdBTF9SRVNUUklDVElPTiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UOgogICAgICAgICAgICAgICAgICAgIC8vIDUuMyBJZiB0aGUge2NvbnRlbnQgdHlwZX0gb2YgdGhlIHtiYXNlIHR5cGUgZGVmaW5pdGlvbn0gaXMgbWl4ZWQuLi4KICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSAhPSBTY2hlbWFUeXBlLk1JWEVEX0NPTlRFTlQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSB0eXBlIHdpdGggYSBtaXhlZCBjb250ZW50IG1vZGVsIGNhbiBvbmx5IHJlc3RyaWN0IGFub3RoZXIgdHlwZSB3aXRoIGEgbWl4ZWQgY29udGVudCBtb2RlbC4iLCBYbWxFcnJvckNvbnRleHQuSUxMRUdBTF9SRVNUUklDVElPTiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vIEZBTExUSFJPVUdICiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuRUxFTUVOVF9DT05URU5UOgogICAgICAgICAgICAgICAgICAgIC8vIDUuMyAuLi4gb3IgdGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSBjb21wbGV4IHR5cGUgZGVmaW5pdGlvbiBpdHNlbGYgaXMgZWxlbWVudC1vbmx5LC4uLgogICAgICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpID09IFNjaGVtYVR5cGUuRU1QVFlfQ09OVEVOVCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgd2l0aCBlbGVtZW50IG9yIG1peGVkIGNvbnRlbnQgY2Fubm90IHJlc3RyaWN0IGFuIGVtcHR5IHR5cGUuIiwgWG1sRXJyb3JDb250ZXh0LklMTEVHQUxfUkVTVFJJQ1RJT04sIGxvY2F0aW9uKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSA9PSBTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgdHlwZSB3aXRoIGVsZW1lbnQgb3IgbWl4ZWQgY29udGVudCBjYW5ub3QgcmVzdHJpY3QgYSBzaW1wbGUgdHlwZS4iLCBYbWxFcnJvckNvbnRleHQuSUxMRUdBTF9SRVNUUklDVElPTiwgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vIDUuMyAuLi4gdGhlbiB0aGUgcGFydGljbGUgb2YgdGhlIGNvbXBsZXggdHlwZSBkZWZpbml0aW9uIGl0c2VsZiBtdXN0IGJlIGEgt3ZhbGlkIHJlc3RyaWN0aW9utyBvZiB0aGUgcGFydGljbGUgb2YgdGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSB7YmFzZSB0eXBlIGRlZmluaXRpb259CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsID0gYmFzZVR5cGUuZ2V0Q29udGVudE1vZGVsKCk7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsID0gc1R5cGUuZ2V0Q29udGVudE1vZGVsKCk7CiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGJhc2VNb2RlbCAhPSBudWxsICYmIGRlcml2ZWRNb2RlbCAhPSBudWxsKTsKICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZU1vZGVsID09IG51bGwgfHwgZGVyaXZlZE1vZGVsID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBYQmVhbkRlYnVnLmxvZ1N0YWNrVHJhY2UoIk51bGwgbW9kZWxzIHRoYXQgd2VyZW4ndCBjYXVnaHQgYnkgRU1QVFlfQ09OVEVOVDogIiArIGJhc2VUeXBlICsgIiAoIiArIGJhc2VNb2RlbCArICIpLCAiICsgc1R5cGUgKyAiICgiICsgZGVyaXZlZE1vZGVsICsgIikiKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIklsbGVnYWwgcmVzdHJpY3Rpb24uIiwgWG1sRXJyb3JDb250ZXh0LklMTEVHQUxfUkVTVFJJQ1RJT04sIGxvY2F0aW9uKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAvLyA1LjMgLi4uICBhcyBkZWZpbmVkIGluIFBhcnRpY2xlIFZhbGlkIChSZXN0cmljdGlvbikgKKczLjkuNikuCiAgICAgICAgICAgICAgICAgICAgTGlzdCBlcnJvcnMgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgICAgICAgICAgICAgYm9vbGVhbiBpc1ZhbGlkID0gaXNQYXJ0aWNsZVZhbGlkUmVzdHJpY3Rpb24oYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgbG9jYXRpb24pOwogICAgICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIG9ubHkgYWRkIHRoZSBsYXN0IGVycm9yLCBiZWNhdXNlIGlzUGFydGljbGVWYWxpZFJlc3RyaWN0aW9uIG1heSBhZGQgZXJyb3JzCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHRoZSBjb2xsZWN0aW9uIHRoYXQgaXQgbGF0ZXIgY2hhbmdlcyBpdHMgbWluZCBhYm91dCwgb3IgaXQgbWF5IChpbmFkdmVydGVudGx5KQogICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3JnZXQgdG8gZGVzY3JpYmUgYW4gZXJyb3IgaW50byB0aGUgY29sbGVjdGlvbi4uLi4KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9ycy5zaXplKCkgPT0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJJbnZhbGlkIHJlc3RyaWN0aW9uLiIsIFhtbEVycm9yQ29udGV4dC5JTExFR0FMX1JFU1RSSUNUSU9OLCBsb2NhdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmdldEVycm9yTGlzdGVuZXIoKS5hZGQoZXJyb3JzLmdldChlcnJvcnMuc2l6ZSgpIC0gMSkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIAogICAgLyoqCiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHR3byBzY2hlbWEgcGFydGljbGUgdHlwZXMsIGEgYmFzZU1vZGVsLCBhbmQgYSBkZXJpdmVkIG1vZGVsIGFuZCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICAgKiBkZXJpdmVkTW9kZWwgY2FuIGJlIGVnaXRpbWF0ZWx5IGJlIHVzZWQgZm9yIHJlc3RyaWN0aW9uLiAgRXJyb3JzIGFyZSBwdXQgaW50byB0aGUgZXJyb3JzIGNvbGxlY3Rpb25zLgogICAgICogQHBhcmFtIGJhc2VNb2RlbCAtIFRoZSBiYXNlIHNjaGVtYSBwYXJ0aWNsZQogICAgICogQHBhcmFtIGRlcml2ZWRNb2RlbCAtIFRoZSBkZXJpdmVkIChyZXN0cmljdGVkKSBzY2hlbWEgcGFydGljbGUKICAgICAqIEBwYXJhbSBlcnJvcnMgLSBJbnZhbGlkIHJlc3RyaWN0aW9uIGVycm9ycyBhcmUgcHV0IGludG8gdGhpcyBjb2xsZWN0aW9uCiAgICAgKiBAcGFyYW0gY29udGV4dAogICAgICogQHJldHVybiBib29sZWFuLCB0cnVlIGlmIHZhbGlkIHJlc3RydWN0aW9uLCBmYWxzZSBpZiBpbnZhbGlkIHJlc3RyaWN0aW9uCiAgICAgKiBACiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1BhcnRpY2xlVmFsaWRSZXN0cmljdGlvbihTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCwgQ29sbGVjdGlvbiBlcnJvcnMsIFhtbE9iamVjdCBjb250ZXh0KSAgewogICAgICAgIGJvb2xlYW4gcmVzdHJpY3Rpb25WYWxpZCA9IGZhbHNlOwogICAgICAgIC8vIDEgVGhleSBhcmUgdGhlIHNhbWUgcGFydGljbGUuCiAgICAgICAgaWYgKGJhc2VNb2RlbC5lcXVhbHMoZGVyaXZlZE1vZGVsKSkgewogICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBJbXBsZW1lbnQgdGFibGUgZGVmaW5lZCBpbiBzY2hlbWEgc3BlYyBvbiByZXN0cmljdGlvbnMgYXQ6CiAgICAgICAgICAgIC8vICAgaHR0cDovL3d3dy53My5vcmcvVFIveG1sc2NoZW1hLTEvI2Nvcy1wYXJ0aWNsZS1yZXN0cmljdAogICAgICAgICAgICBzd2l0Y2ggKGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSkgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuRUxFTUVOVDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSBuYW1lQW5kVHlwZU9LKChTY2hlbWFMb2NhbEVsZW1lbnQpIGJhc2VNb2RlbCwgKFNjaGVtYUxvY2FsRWxlbWVudCkgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRJbnZhbGlkQ29tYmluYXRpb25FcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEludmFsaWRDb21iaW5hdGlvbkVycm9yKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQ0hPSUNFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0SW52YWxpZENvbWJpbmF0aW9uRXJyb3IoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEludmFsaWRDb21iaW5hdGlvbkVycm9yKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQgZmFsc2UgOiBYQmVhbkRlYnVnLmxvZ1N0YWNrVHJhY2UoIlVua25vd24gc2NoZW1hIHR5cGUgZm9yIERlcml2ZWQgVHlwZSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IG5zQ29tcGF0KGJhc2VNb2RlbCwgKFNjaGVtYUxvY2FsRWxlbWVudCkgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gbnNTdWJzZXQoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gbnNSZWN1cnNlQ2hlY2tDYXJkaW5hbGl0eShiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSBuc1JlY3Vyc2VDaGVja0NhcmRpbmFsaXR5KGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gbnNSZWN1cnNlQ2hlY2tDYXJkaW5hbGl0eShiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0IGZhbHNlIDogWEJlYW5EZWJ1Zy5sb2dTdGFja1RyYWNlKCJVbmtub3duIHNjaGVtYSB0eXBlIGZvciBEZXJpdmVkIFR5cGUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gcmVjdXJzZUFzSWZHcm91cChiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0SW52YWxpZENvbWJpbmF0aW9uRXJyb3IoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gcmVjdXJzZShiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEludmFsaWRDb21iaW5hdGlvbkVycm9yKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gcmVjdXJzZVVub3JkZXJlZChiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0IGZhbHNlIDogWEJlYW5EZWJ1Zy5sb2dTdGFja1RyYWNlKCJVbmtub3duIHNjaGVtYSB0eXBlIGZvciBEZXJpdmVkIFR5cGUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gcmVjdXJzZUFzSWZHcm91cChiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0SW52YWxpZENvbWJpbmF0aW9uRXJyb3IoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRJbnZhbGlkQ29tYmluYXRpb25FcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSByZWN1cnNlTGF4KGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gbWFwQW5kU3VtKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQgZmFsc2UgOiBYQmVhbkRlYnVnLmxvZ1N0YWNrVHJhY2UoIlVua25vd24gc2NoZW1hIHR5cGUgZm9yIERlcml2ZWQgVHlwZSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IHJlY3Vyc2VBc0lmR3JvdXAoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEludmFsaWRDb21iaW5hdGlvbkVycm9yKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0SW52YWxpZENvbWJpbmF0aW9uRXJyb3IoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvblZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRJbnZhbGlkQ29tYmluYXRpb25FcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb25WYWxpZCA9IHJlY3Vyc2UoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydCBmYWxzZSA6IFhCZWFuRGVidWcubG9nU3RhY2tUcmFjZSgiVW5rbm93biBzY2hlbWEgdHlwZSBmb3IgRGVyaXZlZCBUeXBlIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgZmFsc2UgOiBYQmVhbkRlYnVnLmxvZ1N0YWNrVHJhY2UoIlVua25vd24gc2NoZW1hIHR5cGUgZm9yIEJhc2UgVHlwZSIpOwoKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJlc3RyaWN0aW9uVmFsaWQ7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBtYXBBbmRTdW0oU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgIHsKICAgICAgICAvLyBtYXBBbmRTdW0gaXMgY2FsbCBpZiBiYXNlOiBDSE9JQ0UsIGRlcml2ZWQ6IFNFUVVFTkNFCiAgICAgICAgYXNzZXJ0IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U7CiAgICAgICAgYXNzZXJ0IGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRTsKICAgICAgICBib29sZWFuIG1hcEFuZFN1bVZhbGlkID0gdHJ1ZTsKICAgICAgICAvLyBTY2hlbWEgQ29tcG9uZW50IENvbnN0cmFpbnQ6IFBhcnRpY2xlIERlcml2YXRpb24gT0sgKFNlcXVlbmNlOkNob2ljZSAtLSBNYXBBbmRTdW0pCiAgICAgICAgLy8gRm9yIGEgc2VxdWVuY2UgZ3JvdXAgcGFydGljbGUgdG8gYmUgYSC3dmFsaWQgcmVzdHJpY3Rpb263IG9mIGEgY2hvaWNlIGdyb3VwIHBhcnRpY2xlIGFsbCBvZiB0aGUgZm9sbG93aW5nCiAgICAgICAgLy8gbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIDEgVGhlcmUgaXMgYSBjb21wbGV0ZSBmdW5jdGlvbmFsIG1hcHBpbmcgZnJvbSB0aGUgcGFydGljbGVzIGluIHRoZSB7cGFydGljbGVzfSBvZiBSIHRvIHRoZSBwYXJ0aWNsZXMgaW4gdGhlCiAgICAgICAgLy8ge3BhcnRpY2xlc30gb2YgQiBzdWNoIHRoYXQgZWFjaCBwYXJ0aWNsZSBpbiB0aGUge3BhcnRpY2xlc30gb2YgUiBpcyBhILd2YWxpZCByZXN0cmljdGlvbrcgb2YgdGhlIHBhcnRpY2xlIGluCiAgICAgICAgLy8gdGhlIHtwYXJ0aWNsZXN9IG9mIEIgaXQgbWFwcyB0byBhcyBkZWZpbmVkIGJ5IFBhcnRpY2xlIFZhbGlkIChSZXN0cmljdGlvbikgKKczLjkuNikuCiAgICAgICAgLy8gaW50ZXJwcmV0YXRpb246ICBlYWNoIHBhcnRpY2xlIGNoaWxkIGluIGRlcml2ZWQgc2hvdWxkIGhhdmUgYSBtYXRjaCBpbiBiYXNlLgogICAgICAgIC8vIDIgVGhlIHBhaXIgY29uc2lzdGluZyBvZiB0aGUgcHJvZHVjdCBvZiB0aGUge21pbiBvY2N1cnN9IG9mIFIgYW5kIHRoZSBsZW5ndGggb2YgaXRzIHtwYXJ0aWNsZXN9IGFuZCB1bmJvdW5kZWQKICAgICAgICAvLyBpZiB7bWF4IG9jY3Vyc30gaXMgdW5ib3VuZGVkIG90aGVyd2lzZSB0aGUgcHJvZHVjdCBvZiB0aGUge21heCBvY2N1cnN9IG9mIFIgYW5kIHRoZSBsZW5ndGggb2YgaXRzIHtwYXJ0aWNsZXN9CiAgICAgICAgLy8gaXMgYSB2YWxpZCByZXN0cmljdGlvbiBvZiBCJ3Mgb2NjdXJyZW5jZSByYW5nZSBhcyBkZWZpbmVkIGJ5IE9jY3VycmVuY2UgUmFuZ2UgT0sgKKczLjkuNikuCiAgICAgICAgLy8gTk9URTogVGhpcyBjbGF1c2UgaXMgaW4gcHJpbmNpcGxlIG1vcmUgcmVzdHJpY3RpdmUgdGhhbiBhYnNvbHV0ZWx5IG5lY2Vzc2FyeSwgYnV0IGluIHByYWN0aWNlIHdpbGwgY292ZXIKICAgICAgICAvLyBhbGwgdGhlIGxpa2VseSBjYXNlcywgYW5kIGlzIG11Y2ggZWFzaWVyIHRvIHNwZWNpZnkgdGhhbiB0aGUgZnVsbHkgZ2VuZXJhbCB2ZXJzaW9uLgogICAgICAgIC8vIE5PVEU6IFRoaXMgY2FzZSBhbGxvd3MgdGhlICJ1bmZvbGRpbmciIG9mIGl0ZXJhdGVkIGRpc2p1bmN0aW9ucyBpbnRvIHNlcXVlbmNlcy4gSXQgbWF5IGJlIHBhcnRpY3VsYXJseSB1c2VmdWwKICAgICAgICAvLyB3aGVuIHRoZSBkaXNqdW5jdGlvbiBpcyBhbiBpbXBsaWNpdCBvbmUgYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2Ygc3Vic3RpdHV0aW9uIGdyb3Vwcy4KCiAgICAgICAgLy8gTWFwIHN0ZXAgLSBmb3IgZWFjaCBtZW1iZXIgb2YgdGhlIGRlcml2ZWQgbW9kZWwncyBwYXJ0aWNsZSBjaGlsZHJlbiBzZWFyY2ggYmFzZSBtb2RlbCdzIHBhcnRpY2xlIGNoaWxkcmVuCiAgICAgICAgLy8gIGZvciBtYXRjaAogICAgICAgIFNjaGVtYVBhcnRpY2xlW10gZGVyaXZlZFBhcnRpY2xlQXJyYXkgPSBkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgIFNjaGVtYVBhcnRpY2xlW10gYmFzZVBhcnRpY2xlQXJyYXkgPSBiYXNlTW9kZWwuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZGVyaXZlZFBhcnRpY2xlQXJyYXkubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgZGVyaXZlZFBhcnRpY2xlID0gZGVyaXZlZFBhcnRpY2xlQXJyYXlbaV07CiAgICAgICAgICAgIGJvb2xlYW4gZm91bmRNYXRjaCA9IGZhbHNlOwogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IGJhc2VQYXJ0aWNsZUFycmF5Lmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBiYXNlUGFydGljbGUgPSBiYXNlUGFydGljbGVBcnJheVtqXTsKICAgICAgICAgICAgICAgIC8vIHJlY3Vyc2UgdG8gY2hlY2sgaWYgdGhlcmUgaXMgYSBtYXRjaAogICAgICAgICAgICAgICAgaWYgKGlzUGFydGljbGVWYWxpZFJlc3RyaWN0aW9uKGJhc2VQYXJ0aWNsZSwgZGVyaXZlZFBhcnRpY2xlLCBlcnJvcnMsIGNvbnRleHQpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYSBtYXRjaCB0aGVuIG5vIG5lZWQgdG8gY2hlY2sgYmFzZSBwYXJ0aWNsZXMgYW55bW9yZQogICAgICAgICAgICAgICAgICAgIGZvdW5kTWF0Y2ggPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghZm91bmRNYXRjaCkgewogICAgICAgICAgICAgICAgbWFwQW5kU3VtVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE1hcHBpbmdFcnJvcigpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gU3VtIHN0ZXAKICAgICAgICBCaWdJbnRlZ2VyIGRlcml2ZWRSYW5nZU1pbiA9IGRlcml2ZWRNb2RlbC5nZXRNaW5PY2N1cnMoKS5tdWx0aXBseShCaWdJbnRlZ2VyLnZhbHVlT2YoZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKS5sZW5ndGgpKTsKICAgICAgICBCaWdJbnRlZ2VyIGRlcml2ZWRSYW5nZU1heCA9IG51bGw7CiAgICAgICAgQmlnSW50ZWdlciBVTkJPVU5ERUQgPSBudWxsOwogICAgICAgIGlmIChkZXJpdmVkTW9kZWwuZ2V0TWF4T2NjdXJzKCkgPT0gVU5CT1VOREVEKSB7CiAgICAgICAgICAgIGRlcml2ZWRSYW5nZU1heCA9IG51bGw7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZGVyaXZlZFJhbmdlTWF4ID0gZGVyaXZlZE1vZGVsLmdldE1heE9jY3VycygpLm11bHRpcGx5KEJpZ0ludGVnZXIudmFsdWVPZihkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVDaGlsZHJlbigpLmxlbmd0aCkpOwogICAgICAgIH0KCiAgICAgICAgLy8gTm93IGNoZWNrIGRlcml2ZWRSYW5nZSAoZGVyaXZlZFJhbmdlTWluIGFuZCBkZXJpdmVkUmFuZ2VNYXgpIGFnYWluc3QgYmFzZSBtb2RlbCBvY2N1cnJlbmNlIHJhbmdlCiAgICAgICAgLy8gU2NoZW1hIENvbXBvbmVudCBDb25zdHJhaW50OiBPY2N1cnJlbmNlIFJhbmdlIE9LCiAgICAgICAgLy8gRm9yIGEgcGFydGljbGUncyBvY2N1cnJlbmNlIHJhbmdlIHRvIGJlIGEgdmFsaWQgcmVzdHJpY3Rpb24gb2YgYW5vdGhlcidzIG9jY3VycmVuY2UgcmFuZ2UgYWxsIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIDEgSXRzIHttaW4gb2NjdXJzfSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIG90aGVyJ3Mge21pbiBvY2N1cnN9LgogICAgICAgIC8vIDIgb25lIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vICAgMi4xIFRoZSBvdGhlcidzIHttYXggb2NjdXJzfSBpcyB1bmJvdW5kZWQuCiAgICAgICAgLy8gICAyLjIgQm90aCB7bWF4IG9jY3Vyc30gYXJlIG51bWJlcnMsIGFuZCB0aGUgcGFydGljbGUncyBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIG90aGVyJ3MuCgogICAgICAgIGlmIChkZXJpdmVkUmFuZ2VNaW4uY29tcGFyZVRvKGJhc2VNb2RlbC5nZXRNaW5PY2N1cnMoKSkgPCAwKSB7CiAgICAgICAgICAgIG1hcEFuZFN1bVZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE9jY3VyZW5jZVJhbmdlTWluRXJyb3JDaG9pY2VTZXF1ZW5jZShkZXJpdmVkUmFuZ2VNaW4sIGJhc2VNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICB9IGVsc2UgaWYgKGJhc2VNb2RlbC5nZXRNYXhPY2N1cnMoKSA9PSBVTkJPVU5ERUQgfHwgZGVyaXZlZFJhbmdlTWF4ICE9IFVOQk9VTkRFRCAmJiBkZXJpdmVkUmFuZ2VNYXguY29tcGFyZVRvKGJhc2VNb2RlbC5nZXRNYXhPY2N1cnMoKSkgPiAwKSB7CiAgICAgICAgICAgIG1hcEFuZFN1bVZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE9jY3VyZW5jZVJhbmdlTWF4RXJyb3JDaG9pY2VTZXF1ZW5jZShkZXJpdmVkUmFuZ2VNYXgsIGJhc2VNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXBBbmRTdW1WYWxpZDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0T2NjdXJlbmNlUmFuZ2VNaW5FcnJvckNob2ljZVNlcXVlbmNlKEJpZ0ludGVnZXIgZGVyaXZlZFJhbmdlTWluLCBTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBUaGUgdG90YWwgbWluT2NjdXJzIGZvciB0aGUgZGVyaXZlZCA8c2VxdWVuY2U+J3MgZWxlbWVudHM6ICIKICAgICAgICAgICAgICAgICsgZGVyaXZlZFJhbmdlTWluLnRvU3RyaW5nKCkKICAgICAgICAgICAgICAgICsgIm11c3Qgbm90IGJlIGxlc3MgdGhhbiB0aGUgYmFzZSA8Y2hvaWNlPidzIG1pbk9jY3VycyAoIgogICAgICAgICAgICAgICAgKyBiYXNlTW9kZWwuZ2V0TWluT2NjdXJzKCkudG9TdHJpbmcoKSArICIpIjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0T2NjdXJlbmNlUmFuZ2VNYXhFcnJvckNob2ljZVNlcXVlbmNlKEJpZ0ludGVnZXIgZGVyaXZlZFJhbmdlTWF4LCBTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBUaGUgdG90YWwgbWF4T2NjdXJzIGZvciB0aGUgZGVyaXZlZCA8c2VxdWVuY2U+J3MgZWxlbWVudHMgKCIKICAgICAgICAgICAgICAgICsgZGVyaXZlZFJhbmdlTWF4LnRvU3RyaW5nKCkKICAgICAgICAgICAgICAgICsgIikgbXVzdCBub3QgYmUgZ3JlYXRlciB0aGFuIHRoZSBiYXNlIDxjaG9pY2U+J3MgbWF4T2NjdXJzICgiCiAgICAgICAgICAgICAgICArIHByaW50TWF4T2NjdXJzKGJhc2VNb2RlbC5nZXRNYXhPY2N1cnMoKSkgKyAiKSI7CiAgICAgICAKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0TWFwcGluZ0Vycm9yKCkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIEF0IGxlYXN0IG9uZSByZXN0cmljdGVkIHR5cGUgZG9lcyBub3QgbWF0Y2guIjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBib29sZWFuIHJlY3Vyc2VBc0lmR3JvdXAoU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgewogICAgICAgIC8vIHJlY3Vyc2VBc0lmR3JvdXAgaXMgY2FsbGVkIGlmOgogICAgICAgIC8vIGJhc2U6IEFMTCwgZGVyaXZlZDogRUxFTUVOVAogICAgICAgIC8vIGJhc2U6IENIT0lDRSwgZGVyaXZlZDogRUxFTUVOVAogICAgICAgIC8vIGJhc2U6IFNFUVVFTkNFLCBkZXJpdmVkOiBFTEVNRU5UCiAgICAgICAgYXNzZXJ0IChiYXNlTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMICYmIGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKQogICAgICAgICAgICAgICAgfHwgKGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0UgJiYgZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQpCiAgICAgICAgICAgICAgICB8fCAoYmFzZU1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFICYmIGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKTsKICAgICAgICAvLyBTY2hlbWEgQ29tcG9uZW50IENvbnN0cmFpbnQ6IFBhcnRpY2xlIERlcml2YXRpb24gT0sgKEVsdDpBbGwvQ2hvaWNlL1NlcXVlbmNlIC0tIFJlY3Vyc2VBc0lmR3JvdXApCgogICAgICAgIC8vIEZvciBhbiBlbGVtZW50IGRlY2xhcmF0aW9uIHBhcnRpY2xlIHRvIGJlIGEgt3ZhbGlkIHJlc3RyaWN0aW9utyBvZiBhIGdyb3VwIHBhcnRpY2xlCiAgICAgICAgLy8gKGFsbCwgY2hvaWNlIG9yIHNlcXVlbmNlKSBhIGdyb3VwIHBhcnRpY2xlIG9mIHRoZSB2YXJpZXR5IGNvcnJlc3BvbmRpbmcgdG8gQidzLCB3aXRoIHttaW4gb2NjdXJzfSBhbmQKICAgICAgICAvLyB7bWF4IG9jY3Vyc30gb2YgMSBhbmQgd2l0aCB7cGFydGljbGVzfSBjb25zaXN0aW5nIG9mIGEgc2luZ2xlIHBhcnRpY2xlIHRoZSBzYW1lIGFzIHRoZSBlbGVtZW50IGRlY2xhcmF0aW9uCiAgICAgICAgLy8gbXVzdCBiZSBhILd2YWxpZCByZXN0cmljdGlvbrcgb2YgdGhlIGdyb3VwIGFzIGRlZmluZWQgYnkgUGFydGljbGUgRGVyaXZhdGlvbiBPSwogICAgICAgIC8vIChBbGw6QWxsLFNlcXVlbmNlOlNlcXVlbmNlIC0tIFJlY3Vyc2UpICinMy45LjYpLCBQYXJ0aWNsZSBEZXJpdmF0aW9uIE9LIChDaG9pY2U6Q2hvaWNlIC0tIFJlY3Vyc2VMYXgpCiAgICAgICAgLy8gKKczLjkuNikgb3IgUGFydGljbGUgRGVyaXZhdGlvbiBPSyAoQWxsOkFsbCxTZXF1ZW5jZTpTZXF1ZW5jZSAtLSBSZWN1cnNlKSAopzMuOS42KSwgZGVwZW5kaW5nIG9uIHdoZXRoZXIKICAgICAgICAvLyB0aGUgZ3JvdXAgaXMgYWxsLCBjaG9pY2Ugb3Igc2VxdWVuY2UKCiAgICAgICAgLy8gaW50ZXJwcmV0YXRpb246ICBtYWtlIGEgZmFrZSBncm91cCBvZiB0aGUgcmlnaHQgdHlwZSwgd2l0aCBtaW4gb2NjdXJzIGFuZCBtYXggb2NjdXJzIG9mIDEKICAgICAgICBTY2hlbWFQYXJ0aWNsZUltcGwgYXNJZlBhcnQgPSBuZXcgU2NoZW1hUGFydGljbGVJbXBsKCk7CiAgICAgICAgYXNJZlBhcnQuc2V0UGFydGljbGVUeXBlKGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSk7CiAgICAgICAgYXNJZlBhcnQuc2V0TWluT2NjdXJzKEJpZ0ludGVnZXIuT05FKTsKICAgICAgICBhc0lmUGFydC5zZXRNYXhPY2N1cnMoQmlnSW50ZWdlci5PTkUpOwogICAgICAgIGFzSWZQYXJ0LnNldFBhcnRpY2xlQ2hpbGRyZW4obmV3IFNjaGVtYVBhcnRpY2xlW10geyBkZXJpdmVkTW9kZWwgfSk7CiAgICAgICAgCiAgICAgICAgLy8gdGhlIHJlY3Vyc2UKICAgICAgICByZXR1cm4gaXNQYXJ0aWNsZVZhbGlkUmVzdHJpY3Rpb24oYmFzZU1vZGVsLCBhc0lmUGFydCwgZXJyb3JzLCBjb250ZXh0KTsgCiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiByZWN1cnNlTGF4KFNjaGVtYVBhcnRpY2xlIGJhc2VNb2RlbCwgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsLCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpICB7CiAgICAgICAgLy8gcmVjdXJzZUxheCBpcyBjYWxsZWQgaWYgYmFzZTogQ0hPSUNFLCBkZXJpdmVkOiBDSE9JQ0UKICAgICAgICBhc3NlcnQgYmFzZU1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkNIT0lDRSAmJiBkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQ0hPSUNFOwogICAgICAgIGJvb2xlYW4gcmVjdXJzZUxheFZhbGlkID0gdHJ1ZTsKICAgICAgICAvL1NjaGVtYSBDb21wb25lbnQgQ29uc3RyYWludDogUGFydGljbGUgRGVyaXZhdGlvbiBPSyAoQ2hvaWNlOkNob2ljZSAtLSBSZWN1cnNlTGF4KQogICAgICAgIC8vIEZvciBhIGNob2ljZSBncm91cCBwYXJ0aWNsZSB0byBiZSBhILd2YWxpZCByZXN0cmljdGlvbrcgb2YgYW5vdGhlciBjaG9pY2UgZ3JvdXAgcGFydGljbGUgYWxsIG9mIHRoZQogICAgICAgIC8vIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgLy8gMSBSJ3Mgb2NjdXJyZW5jZSByYW5nZSBpcyBhIHZhbGlkIHJlc3RyaWN0aW9uIG9mIEIncyBvY2N1cnJlbmNlIHJhbmdlIGFzIGRlZmluZWQgYnkgT2NjdXJyZW5jZQogICAgICAgIC8vIFJhbmdlIE9LICinMy45LjYpOwogICAgICAgIC8vIDIgVGhlcmUgaXMgYSBjb21wbGV0ZSC3b3JkZXItcHJlc2VydmluZ7cgZnVuY3Rpb25hbCBtYXBwaW5nIGZyb20gdGhlIHBhcnRpY2xlcyBpbiB0aGUge3BhcnRpY2xlc30gb2YgUgogICAgICAgIC8vIHRvIHRoZSBwYXJ0aWNsZXMgaW4gdGhlIHtwYXJ0aWNsZXN9IG9mIEIgc3VjaCB0aGF0IGVhY2ggcGFydGljbGUgaW4gdGhlIHtwYXJ0aWNsZXN9IG9mIFIgaXMgYQogICAgICAgIC8vILd2YWxpZCByZXN0cmljdGlvbrcgb2YgdGhlIHBhcnRpY2xlIGluIHRoZSB7cGFydGljbGVzfSBvZiBCIGl0IG1hcHMgdG8gYXMgZGVmaW5lZCBieQogICAgICAgIC8vIFBhcnRpY2xlIFZhbGlkIChSZXN0cmljdGlvbikgKKczLjkuNikuCiAgICAgICAgLy8gTk9URTogQWx0aG91Z2ggdGhlILd2YWxpZGF0aW9utyBzZW1hbnRpY3Mgb2YgYSBjaG9pY2UgZ3JvdXAgZG9lcyBub3QgZGVwZW5kIG9uIHRoZSBvcmRlciBvZiBpdHMgcGFydGljbGVzLAogICAgICAgIC8vIGRlcml2ZWQgY2hvaWNlIGdyb3VwcyBhcmUgcmVxdWlyZWQgdG8gbWF0Y2ggdGhlIG9yZGVyIG9mIHRoZWlyIGJhc2UgaW4gb3JkZXIgdG8gc2ltcGxpZnkKICAgICAgICAvLyBjaGVja2luZyB0aGF0IHRoZSBkZXJpdmF0aW9uIGlzIE9LLgogICAgICAgIC8vIGludGVycHJldGF0aW9uOiAgY2hlY2sgZGVyaXZlZCBjaG9pY2VzIGZvciBtYXRjaCBpbiBvcmRlciwgbXVzdCBnZXQgYW4gaW4gb3JkZXIgbWF0Y2ggb24gYSBiYXNlIHBhcnRpY2xlLAogICAgICAgIC8vICAgICAgICAgICAgICAgICAgZG9uJ3QgbmVlZCB0byBjaGVjayBpZiBiYXNlIHBhcnRpY2xlcyBhcmUgc2tpcHBhYmxlLiAgYSBsb3QgbGlrZSByZWN1cnNlCgogICAgICAgIGlmICghb2NjdXJyZW5jZVJhbmdlT0soYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCkpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICAvLyBjeWNsZSB0aHJ1IGJvdGggZGVyaXZlZCBwYXJ0aWNsZSBjaGlsZHJlbiBhbmQgYmFzZSBwYXJ0aWNsZSBjaGlsZHJlbiBsb29raW5nIGZvciBtYXRjaGVzCiAgICAgICAgLy8gIGlmIHRoZSBkZXJpdmVkIHBhcnRpY2xlIGRvZXMgbm90IG1hdGNoIHRoZSBiYXNlIHBhcnRpY2xlIHRoZW4gYmFzZSBwYXJ0aWNsZSBjYW4gYmUgc2tpcHBlZAoKICAgICAgICBTY2hlbWFQYXJ0aWNsZVtdIGRlcml2ZWRQYXJ0aWNsZUFycmF5ID0gZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICBTY2hlbWFQYXJ0aWNsZVtdIGJhc2VQYXJ0aWNsZUFycmF5ID0gYmFzZU1vZGVsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICBpbnQgaSA9IDAsIGogPSAwOwogICAgICAgIGZvciAoOyBpIDwgZGVyaXZlZFBhcnRpY2xlQXJyYXkubGVuZ3RoICYmIGogPCBiYXNlUGFydGljbGVBcnJheS5sZW5ndGg7KSB7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRQYXJ0aWNsZSA9IGRlcml2ZWRQYXJ0aWNsZUFycmF5W2ldOwogICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBiYXNlUGFydGljbGUgPSBiYXNlUGFydGljbGVBcnJheVtqXTsKICAgICAgICAgICAgLy8gdHJ5IHRvIG1hdGNoIHRoZSB0d28gcGFydGljbGVzIGJ5IHJlY3Vyc2luZwogICAgICAgICAgICBpZiAoaXNQYXJ0aWNsZVZhbGlkUmVzdHJpY3Rpb24oYmFzZVBhcnRpY2xlLCBkZXJpdmVkUGFydGljbGUsIGVycm9ycywgY29udGV4dCkpIHsKICAgICAgICAgICAgICAgIC8vIGNvb2wgZm91bmQgYSBtYXRjaCwgaW5jcmVtZW50IGJvdGggaW5kZXhlcwogICAgICAgICAgICAgICAgaSsrOwogICAgICAgICAgICAgICAgaisrOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gZGlkIG5vdCBtYXRjaCwgaW5jcmVtZW50IHRoZSBiYXNlIHBhcnRpY2xlIGFycmF5IGluZGV4IG9ubHkKICAgICAgICAgICAgICAgIC8vIE9rLCBsZXQncyBza2lwIHRoaXMgYmFzZSBwYXJ0aWNsZSwgaW5jcmVtZW50IGJhc2UgcGFydGljbGUgYXJyYXkgaW5kZXggb25seQogICAgICAgICAgICAgICAgaisrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBvaywgZ290IHRvIHRoZSBlbmQgb2Ygb25lIG9mIHRoZSBhcnJheXMKICAgICAgICAvLyBpZiBhdCBlbmQgb2YgYmFzZSBwYXJ0aWNsZSBhcnJheSBhbmQgbm90IGF0IHRoZSBlbmQgb2YgZGVyaXZlZCBwYXJ0aWNsZSBhcnJheSB0aGVuIHJlbWFpbmluZyBkZXJpdmVkCiAgICAgICAgLy8gIHBhcnRpY2xlcyBtdXN0IG5vdCBtYXRjaAogICAgICAgIGlmIChpIDwgZGVyaXZlZFBhcnRpY2xlQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgICAgIHJlY3Vyc2VMYXhWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICBTdHJpbmcgbWVzc2FnZSA9ICJGb3VuZCBkZXJpdmVkIHBhcnRpY2xlcyB0aGF0IGFyZSBub3QgbWF0Y2hlZCBpbiB0aGUgYmFzZSBjb250ZW50IG1vZGVsLiI7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdERlcml2ZWRNYXBwaW5nRXJyb3IobWVzc2FnZSwgYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgfQoKCiAgICAgICAgcmV0dXJuIHJlY3Vyc2VMYXhWYWxpZDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBib29sZWFuIHJlY3Vyc2VVbm9yZGVyZWQoU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgewogICAgICAgIC8vIHJlY3Vyc2VVbm9yZGVyIGlzIGNhbGxlZCB3aGVuIGJhc2U6IEFMTCBhbmQgZGVyaXZlZDogU0VRCiAgICAgICAgYXNzZXJ0IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5BTEwgJiYgZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOwogICAgICAgIGJvb2xlYW4gcmVjdXJzZVVub3JkZXJlZFZhbGlkID0gdHJ1ZTsKICAgICAgICAvLyBTY2hlbWEgQ29tcG9uZW50IENvbnN0cmFpbnQ6IFBhcnRpY2xlIERlcml2YXRpb24gT0sgKFNlcXVlbmNlOkFsbCAtLSBSZWN1cnNlVW5vcmRlcmVkKQogICAgICAgIC8vIEZvciBhIHNlcXVlbmNlIGdyb3VwIHBhcnRpY2xlIHRvIGJlIGEgt3ZhbGlkIHJlc3RyaWN0aW9utyBvZiBhbiBhbGwgZ3JvdXAgcGFydGljbGUgYWxsIG9mIHRoZQogICAgICAgIC8vIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgLy8gMSBSJ3Mgb2NjdXJyZW5jZSByYW5nZSBpcyBhIHZhbGlkIHJlc3RyaWN0aW9uIG9mIEIncyBvY2N1cnJlbmNlIHJhbmdlIGFzIGRlZmluZWQgYnkKICAgICAgICAvLyBPY2N1cnJlbmNlIFJhbmdlIE9LICinMy45LjYpLgogICAgICAgIC8vIDIgVGhlcmUgaXMgYSBjb21wbGV0ZSBmdW5jdGlvbmFsIG1hcHBpbmcgZnJvbSB0aGUgcGFydGljbGVzIGluIHRoZSB7cGFydGljbGVzfSBvZiBSIHRvIHRoZSBwYXJ0aWNsZXMKICAgICAgICAvLyBpbiB0aGUge3BhcnRpY2xlc30gb2YgQiBzdWNoIHRoYXQgYWxsIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIDIuMSBObyBwYXJ0aWNsZSBpbiB0aGUge3BhcnRpY2xlc30gb2YgQiBpcyBtYXBwZWQgdG8gYnkgbW9yZSB0aGFuIG9uZSBvZiB0aGUgcGFydGljbGVzIGluCiAgICAgICAgLy8gdGhlIHtwYXJ0aWNsZXN9IG9mIFI7CiAgICAgICAgLy8gMi4yIEVhY2ggcGFydGljbGUgaW4gdGhlIHtwYXJ0aWNsZXN9IG9mIFIgaXMgYSC3dmFsaWQgcmVzdHJpY3Rpb263IG9mIHRoZSBwYXJ0aWNsZSBpbiB0aGUge3BhcnRpY2xlc30gb2YgQgogICAgICAgIC8vIGl0IG1hcHMgdG8gYXMgZGVmaW5lZCBieSBQYXJ0aWNsZSBWYWxpZCAoUmVzdHJpY3Rpb24pICinMy45LjYpOwogICAgICAgIC8vIDIuMyBBbGwgcGFydGljbGVzIGluIHRoZSB7cGFydGljbGVzfSBvZiBCIHdoaWNoIGFyZSBub3QgbWFwcGVkIHRvIGJ5IGFueSBwYXJ0aWNsZSBpbiB0aGUge3BhcnRpY2xlc30KICAgICAgICAvLyBvZiBSIGFyZSC3ZW1wdGlhYmxltyBhcyBkZWZpbmVkIGJ5IFBhcnRpY2xlIEVtcHRpYWJsZSAopzMuOS42KS4KICAgICAgICAvLyBOT1RFOiBBbHRob3VnaCB0aGlzIGNsYXVzZSBhbGxvd3MgcmVvcmRlcmluZywgYmVjYXVzZSBvZiB0aGUgbGltaXRzIG9uIHRoZSBjb250ZW50cyBvZiBhbGwgZ3JvdXBzIHRoZQogICAgICAgIC8vIGNoZWNraW5nIHByb2Nlc3MgY2FuIHN0aWxsIGJlIGRldGVybWluaXN0aWMuCiAgICAgICAgLy8gMSwgMi4yLCBhbmQgMi4zIGFyZSB0aGUgc2FtZSBhcyByZWN1cnNlLCBzbyBkbyAyLjEgYW5kIHRoZW4gY2FsbCByZWN1cnNlCgogICAgICAgIGlmICghb2NjdXJyZW5jZVJhbmdlT0soYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCkpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgLy8gcmVhZCBiYXNlUGFydGljbGUgYXJyYXkgUU5hbWVzIGludG8gaGFzaG1hcAogICAgICAgIFNjaGVtYVBhcnRpY2xlW10gYmFzZVBhcnRpY2xlcyA9IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgSGFzaE1hcCBiYXNlUGFydGljbGVNYXAgPSBuZXcgSGFzaE1hcCgxMCk7CiAgICAgICAgT2JqZWN0IE1BUFBFRCA9IG5ldyBPYmplY3QoKTsKICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBoYXNobWFwCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBiYXNlUGFydGljbGVzLmxlbmd0aDsgaSsrKQogICAgICAgICAgICBiYXNlUGFydGljbGVNYXAucHV0KGJhc2VQYXJ0aWNsZXNbaV0uZ2V0TmFtZSgpLCBiYXNlUGFydGljbGVzW2ldKTsKICAgICAgICAKICAgICAgICAvLyBnbyB0aHJ1IHRoZSBzZXF1ZW5jZSAoZGVyaXZlZCBtb2RlbCdzIGNoaWxkcmVuKSBhbmQgY2hlY2sgb2ZmIGZyb20gYmFzZSBwYXJ0aWNsZSBtYXAKICAgICAgICBTY2hlbWFQYXJ0aWNsZVtdIGRlcml2ZWRQYXJ0aWNsZXMgPSBkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZGVyaXZlZFBhcnRpY2xlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBtYXRjaGVkQmFzZVBhcnRpY2xlID0gKFNjaGVtYVBhcnRpY2xlKSBiYXNlUGFydGljbGVNYXAuZ2V0KGRlcml2ZWRQYXJ0aWNsZXNbaV0uZ2V0TmFtZSgpKTsKICAgICAgICAgICAgaWYgKG1hdGNoZWRCYXNlUGFydGljbGUgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgcmVjdXJzZVVub3JkZXJlZFZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRJbnZhbGlkQWxsU2VxTWFwcGluZ0Vycm9yKCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gZ290IGEgbWF0Y2gKICAgICAgICAgICAgICAgIGlmIChtYXRjaGVkQmFzZVBhcnRpY2xlID09IE1BUFBFRCkgewogICAgICAgICAgICAgICAgICAgIC8vIHdob2EsIHRoaXMgYmFzZSBwYXJ0aWNsZSBoYXMgYWxyZWFkeSBiZWVuIG1hdGNoZWQgKHNlZSAyLjEgYWJvdmUpCiAgICAgICAgICAgICAgICAgICAgcmVjdXJzZVVub3JkZXJlZFZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0TWFwcGVkTW9yZVRoYW5PbmNlRXJyb3IoYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGlmIChkZXJpdmVkUGFydGljbGVzW2ldLmdldE1heE9jY3VycygpID09IG51bGwgfHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcml2ZWRQYXJ0aWNsZXNbaV0uZ2V0TWF4T2NjdXJzKCkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm8gZGVyaXZlZCBwYXJ0aWNsZXMgY2FuIGhhdmUgYSBtYXggb2NjdXJzIGdyZWF0ZXIgdGhhbiAxCiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2VVbm9yZGVyZWRWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRBbGxTZXFNYXhPY2N1cnNHcmVhdGVyVGhhbjFFcnJvcihkZXJpdmVkUGFydGljbGVzW2ldKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1BhcnRpY2xlVmFsaWRSZXN0cmljdGlvbihtYXRjaGVkQmFzZVBhcnRpY2xlLCBkZXJpdmVkUGFydGljbGVzW2ldLCBlcnJvcnMsIGNvbnRleHQpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBoYXZlIGFuIGVycm9yCiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2VVbm9yZGVyZWRWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgLy8gZXZlcnl0aGluZyBpcyBjb29sLCBnb3QgYSBtYXRjaCwgdXBkYXRlIHRvIE1BUFBFRAogICAgICAgICAgICAgICAgICAgIGJhc2VQYXJ0aWNsZU1hcC5wdXQoZGVyaXZlZFBhcnRpY2xlc1tpXS5nZXROYW1lKCksIE1BUFBFRCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIGlmIGV2ZXJ5dGhpbmcgaXMgY29vbCBzbyBmYXIgdGhlbiBjaGVjayB0byBzZWUgaWYgYW55IGJhc2UgcGFydGljbGVzIGFyZSBub3QgbWF0Y2hlZAogICAgICAgIGlmIChyZWN1cnNlVW5vcmRlcmVkVmFsaWQpIHsKICAgICAgICAgICAgLy8gZ2V0IGFsbCB0aGUgaGFzaG1hcCBrZXlzIGFuZCBsb29wIHRocnUgbG9va2luZyBmb3IgTk9UX01BUFBFRAogICAgICAgICAgICBTZXQgYmFzZVBhcnRpY2xlQ29sbGVjdGlvbiA9IGJhc2VQYXJ0aWNsZU1hcC5rZXlTZXQoKTsKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBpdGVyYXRvciA9IGJhc2VQYXJ0aWNsZUNvbGxlY3Rpb24uaXRlcmF0b3IoKTsgaXRlcmF0b3IuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgUU5hbWUgYmFzZVBhcnRpY2xlUU5hbWUgPSAoUU5hbWUpIGl0ZXJhdG9yLm5leHQoKTsKICAgICAgICAgICAgICAgIGlmIChiYXNlUGFydGljbGVNYXAuZ2V0KGJhc2VQYXJ0aWNsZVFOYW1lKSAhPSBNQVBQRUQgJiYgISgoU2NoZW1hUGFydGljbGUpYmFzZVBhcnRpY2xlTWFwLmdldChiYXNlUGFydGljbGVRTmFtZSkpLmlzU2tpcHBhYmxlKCkpIHsKICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGJhc2UgcGFydGljbGUgd2FzIG5vdCBtYXBwZWQgYW5kIGlzIG5vdCAicGFydGljbGUgZW1wdGlhYmxlIiAoc2tpcHBhYmxlKQogICAgICAgICAgICAgICAgICAgIHJlY3Vyc2VVbm9yZGVyZWRWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEdyb3VwTWFwcGluZ0Vycm9yKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVjdXJzZVVub3JkZXJlZFZhbGlkOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXRBbGxTZXFNYXhPY2N1cnNHcmVhdGVyVGhhbjFFcnJvcihTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBUaGUgIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRNb2RlbCkKICAgICAgICAgICAgICAgICsgIiBoYXMgYSBtYXhPY2N1cnMgZ3JlYXQgdGhhbiAxICgiCiAgICAgICAgICAgICAgICArIHByaW50TWF4T2NjdXJzKGRlcml2ZWRNb2RlbC5nZXRNYXhPY2N1cnMoKSkKICAgICAgICAgICAgICAgICsgIikuICBXaGVuIHJlc3RyaWN0aW5nIGFuIDxhbGw+IHdpdGggYSA8c2VxdWVuY2U+LCBubyA8ZWxlbWVudD4gY2FuIGhhdmUgYSBtYXhPY2N1cnMgPiAxIjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0SW52YWxpZEFsbFNlcU1hcHBpbmdFcnJvcigpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBFYWNoIGVsZW1lbnQgaW4gdGhlIGRlcml2ZWQgY29udGVudCBtb2RlbCBtdXN0IG1hdGNoIGFuIGVsZW1lbnQgaW4gdGhlIGJhc2UgIgogICAgICAgICAgICAgICAgKyAiY29udGVudCBtb2RlbC4iOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXRHcm91cE1hcHBpbmdFcnJvcihTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIFRoZSBtZW1iZXJzIG9mIHRoZSBkZXJpdmVkIGNvbnRlbnQgbW9kZWwgbXVzdCBtYXRjaCB0aGUgbWVtYmVycyBvZiB0aGUgYmFzZSAiCiAgICAgICAgICAgICAgICArICIgY29udGVudCBtb2RlbCB1bmxlc3MgdGhlIG1lbWJlciBvZiB0aGUgYmFzZSBjb250ZW50IG1vZGVsIGlzIG9wdGlvbmFsIChwYXJ0aWNsZSBlbXB0aWFibGUpLiI7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGZvcm1hdE1hcHBlZE1vcmVUaGFuT25jZUVycm9yKFNjaGVtYVBhcnRpY2xlIGJhc2VNb2RlbCwgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsKSB7CiAgICAgICAgcmV0dXJuICJJbnZhbGlkIFJlc3RyaWN0aW9uLiAgV2hlbiB1c2luZyBhIDxzZXF1ZW5jZT4gdG8gcmVzdHJpY3QgYW4gPGFsbD4gdGhlIGVsZW1lbnRzIGluIHRoZSA8YWxsPiBjYW4gYmUgbWFwcGVkIG9ubHkgb25jZS4gIgogICAgICAgICAgICAgICAgKyAiIEZvdW5kIGVsZW1lbnQgaW4gdGhlIDxzZXF1ZW5jZT4gdGhhdCBtYXBzIGFuIGVsZW1lbnQgaW4gdGhlIDxhbGw+IG1vcmUgdGhhbiBvbmNlLiI7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiByZWN1cnNlKFNjaGVtYVBhcnRpY2xlIGJhc2VNb2RlbCwgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsLCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpIHsKICAgICAgICAvLyByZWN1cnNlIGlzIGNhbGxlZCB3aGVuIGJhc2U6IEFMTCBkZXJpdmVkOiBBTEwgb3IgYmFzZTogU0VRVUVOQ0UgZGVyaXZlZDogU0VRVUVOQ0UKICAgICAgICBib29sZWFuIHJlY3Vyc2VWYWxpZCA9IHRydWU7CiAgICAgICAgLy8gRm9yIGFuIGFsbCBvciBzZXF1ZW5jZSBncm91cCBwYXJ0aWNsZSB0byBiZSBhILd2YWxpZCByZXN0cmljdGlvbrcgb2YgYW5vdGhlciBncm91cCBwYXJ0aWNsZSB3aXRoIHRoZSBzYW1lCiAgICAgICAgLy8ge2NvbXBvc2l0b3J9IGFsbCBvZiB0aGUgZm9sbG93aW5nIG11c3QgYmUgdHJ1ZToKICAgICAgICAvLyAxIFIncyBvY2N1cnJlbmNlIHJhbmdlIGlzIGEgdmFsaWQgcmVzdHJpY3Rpb24gb2YgQidzIG9jY3VycmVuY2UgcmFuZ2UgYXMgZGVmaW5lZCBieQogICAgICAgIC8vIE9jY3VycmVuY2UgUmFuZ2UgT0sgKKczLjkuNikuCiAgICAgICAgLy8gMiBUaGVyZSBpcyBhIGNvbXBsZXRlILdvcmRlci1wcmVzZXJ2aW5ntyBmdW5jdGlvbmFsIG1hcHBpbmcgZnJvbSB0aGUgcGFydGljbGVzIGluIHRoZSB7cGFydGljbGVzfSBvZiBSIHRvCiAgICAgICAgLy8gdGhlIHBhcnRpY2xlcyBpbiB0aGUge3BhcnRpY2xlc30gb2YgQiBzdWNoIHRoYXQgYWxsIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vICAgMi4xIEVhY2ggcGFydGljbGUgaW4gdGhlIHtwYXJ0aWNsZXN9IG9mIFIgaXMgYSC3dmFsaWQgcmVzdHJpY3Rpb263IG9mIHRoZSBwYXJ0aWNsZSBpbiB0aGUge3BhcnRpY2xlc30KICAgICAgICAvLyAgIG9mIEIgaXQgbWFwcyB0byBhcyBkZWZpbmVkIGJ5IFBhcnRpY2xlIFZhbGlkIChSZXN0cmljdGlvbikgKKczLjkuNikuCiAgICAgICAgLy8gICAyLjIgQWxsIHBhcnRpY2xlcyBpbiB0aGUge3BhcnRpY2xlc30gb2YgQiB3aGljaCBhcmUgbm90IG1hcHBlZCB0byBieSBhbnkgcGFydGljbGUgaW4gdGhlIHtwYXJ0aWNsZXN9CiAgICAgICAgLy8gICBvZiBSIGFyZSC3ZW1wdGlhYmxltyBhcyBkZWZpbmVkIGJ5IFBhcnRpY2xlIEVtcHRpYWJsZSAopzMuOS42KS4KICAgICAgICAvLyBOT1RFOiBBbHRob3VnaCB0aGUgt3ZhbGlkYXRpb263IHNlbWFudGljcyBvZiBhbiBhbGwgZ3JvdXAgZG9lcyBub3QgZGVwZW5kIG9uIHRoZSBvcmRlciBvZiBpdHMgcGFydGljbGVzLAogICAgICAgIC8vIGRlcml2ZWQgYWxsIGdyb3VwcyBhcmUgcmVxdWlyZWQgdG8gbWF0Y2ggdGhlIG9yZGVyIG9mIHRoZWlyIGJhc2UgaW4gb3JkZXIgdG8gc2ltcGxpZnkgY2hlY2tpbmcgdGhhdAogICAgICAgIC8vIHRoZSBkZXJpdmF0aW9uIGlzIE9LLgogICAgICAgIC8vIFtEZWZpbml0aW9uOl0gIEEgY29tcGxldGUgZnVuY3Rpb25hbCBtYXBwaW5nIGlzIG9yZGVyLXByZXNlcnZpbmcgaWYgZWFjaCBwYXJ0aWNsZSByIGluIHRoZSBkb21haW4gUiBtYXBzCiAgICAgICAgLy8gdG8gYSBwYXJ0aWNsZSBiIGluIHRoZSByYW5nZSBCIHdoaWNoIGZvbGxvd3MgKG5vdCBuZWNlc3NhcmlseSBpbW1lZGlhdGVseSkgdGhlIHBhcnRpY2xlIGluIHRoZSByYW5nZSBCCiAgICAgICAgLy8gbWFwcGVkIHRvIGJ5IHRoZSBwcmVkZWNlc3NvciBvZiByLCBpZiBhbnksIHdoZXJlICJwcmVkZWNlc3NvciIgYW5kICJmb2xsb3dzIiBhcmUgZGVmaW5lZCB3aXRoIHJlc3BlY3QgdG8KICAgICAgICAvLyB0aGUgb3JkZXIgb2YgdGhlIGxpc3RzIHdoaWNoIGNvbnN0aXR1dGUgUiBhbmQgQi4KCiAgICAgICAgaWYgKCFvY2N1cnJlbmNlUmFuZ2VPSyhiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KSkgewogICAgICAgICAgICAvLyBlcnJvciBtZXNzYWdlIGlzIGZvcm1hdHRlZCBpbiBvY2N1cnJlbmNSYW5nZU9LIC4uLgogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIC8vIGN5Y2xlIHRocnUgYm90aCBkZXJpdmVkIHBhcnRpY2xlIGNoaWxkcmVuIGFuZCBiYXNlIHBhcnRpY2xlIGNoaWxkcmVuIGxvb2tpbmcgZm9yIG1hdGNoZXMKICAgICAgICAvLyAgaWYgdGhlIGRlcml2ZWQgcGFydGljbGUgZG9lcyBub3QgbWF0Y2ggdGhlIGJhc2UgcGFydGljbGUgdGhlbiBiYXNlIHBhcnRpY2xlIGNhbiBiZSBza2lwcGVkIGlmIGl0IGlzCiAgICAgICAgLy8gIHNraXBwYWJsZSAoc2FtZSBhcyAicGFydGljbGUgZW1wdGlhYmxlIikgb3RoZXJ3aXNlIGlzIGFuIGludmFsaWQgcmVzdHJpY3Rpb24uCiAgICAgICAgLy8gYWZ0ZXIgdGhlIGRlcml2ZWQgcGFydGljbGVzIGhhdmUgYmVlbiBjeWNsZWQgaWYgdGhlcmUgYXJlIGFueSBiYXNlIHBhcnRpY2xlcyBsZWZ0IG92ZXIgdGhlbiB0aGV5CiAgICAgICAgLy8gIG11c3QgYmUgc2tpcHBhYmxlIG9yIGludmFsaWQgcmVzdHJpY3Rpb24KCiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBkZXJpdmVkUGFydGljbGVBcnJheSA9IGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBiYXNlUGFydGljbGVBcnJheSA9IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgaW50IGkgPSAwLCBqID0gMDsKICAgICAgICBmb3IgKDsgaSA8IGRlcml2ZWRQYXJ0aWNsZUFycmF5Lmxlbmd0aCAmJiBqIDwgYmFzZVBhcnRpY2xlQXJyYXkubGVuZ3RoOykgewogICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkUGFydGljbGUgPSBkZXJpdmVkUGFydGljbGVBcnJheVtpXTsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgYmFzZVBhcnRpY2xlID0gYmFzZVBhcnRpY2xlQXJyYXlbal07CiAgICAgICAgICAgIC8vIHRyeSB0byBtYXRjaCB0aGUgdHdvIHBhcnRpY2xlcyBieSByZWN1cnNpbmcKICAgICAgICAgICAgaWYgKGlzUGFydGljbGVWYWxpZFJlc3RyaWN0aW9uKGJhc2VQYXJ0aWNsZSwgZGVyaXZlZFBhcnRpY2xlLCBlcnJvcnMsIGNvbnRleHQpKSB7CiAgICAgICAgICAgICAgICAvLyBjb29sIGZvdW5kIGEgbWF0Y2gsIGluY3JlbWVudCBib3RoIGluZGV4ZXMKICAgICAgICAgICAgICAgIGkrKzsKICAgICAgICAgICAgICAgIGorKzsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIGRpZCBub3QgbWF0Y2gsIGluY3JlbWVudCB0aGUgYmFzZSBwYXJ0aWNsZSBhcnJheSBpbmRleCBvbmx5CiAgICAgICAgICAgICAgICAvLyAgdGhhdCdzIG9rIGlmIHRoZSBiYXNlIHBhcnRpY2xlIGlzIHNraXBwYWJsZQogICAgICAgICAgICAgICAgaWYgKGJhc2VQYXJ0aWNsZS5pc1NraXBwYWJsZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gT2ssIGxldCdzIHNraXAgdGhpcyBiYXNlIHBhcnRpY2xlLCBpbmNyZW1lbnQgYmFzZSBwYXJ0aWNsZSBhcnJheSBpbmRleCBvbmx5CiAgICAgICAgICAgICAgICAgICAgaisrOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyB3aG9hLCBwYXJ0aWNsZXMgYXJlIG5vdCB2YWxpZCByZXN0cmljdGlvbnMgYW5kIGJhc2UgaXMgbm90IHNraXBwYWJsZSAtIEVSUk9SCiAgICAgICAgICAgICAgICAgICAgcmVjdXJzZVZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgU3RyaW5nIG1lc3NhZ2UgPSAiRm91bmQgbm9uLW9wdGlvbmFsIHBhcnRpY2xlIHRoYXQgaXMgbm90IG1hcHBlZCBpbiBiYXNlIGNvbnRlbnQgbW9kZWwuIjsKICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXREZXJpdmVkTWFwcGluZ0Vycm9yKG1lc3NhZ2UsIGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBvaywgZ290IHRvIHRoZSBlbmQgb2Ygb25lIG9mIHRoZSBhcnJheXMKICAgICAgICAvLyBpZiBhdCBlbmQgb2YgYmFzZSBwYXJ0aWNsZSBhcnJheSBhbmQgbm90IGF0IHRoZSBlbmQgb2YgZGVyaXZlZCBwYXJ0aWNsZSBhcnJheSB0aGVuIHJlbWFpbmluZyBkZXJpdmVkCiAgICAgICAgLy8gIHBhcnRpY2xlcyBtdXN0IG5vdCBtYXRjaAogICAgICAgIGlmIChpIDwgZGVyaXZlZFBhcnRpY2xlQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgICAgIHJlY3Vyc2VWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICBTdHJpbmcgbWVzc2FnZSA9ICJGb3VuZCBkZXJpdmVkIHBhcnRpY2xlcyB0aGF0IGFyZSBub3QgbWF0Y2hlZCBpbiB0aGUgYmFzZSBjb250ZW50IG1vZGVsLiI7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdERlcml2ZWRNYXBwaW5nRXJyb3IobWVzc2FnZSwgYmFzZU1vZGVsLCBkZXJpdmVkTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gaWYgYXQgZW5kIG9mIGRlcml2ZWQgcGFydGljbGUgYXJyYXkgYW5kIG5vdCBhdCBlbmQgb2YgYmFzZSBwYXJ0aWNsZSBhcnJheSB0aGVuIGNoY2sgcmVtYWluaW5nCiAgICAgICAgICAgIC8vICBiYXNlIHBhcnRpY2xlcyB0byBhc3N1cmUgdGhleSBhcmUgc2tpcHBhYmxlCiAgICAgICAgICAgIGlmIChqIDwgYmFzZVBhcnRpY2xlQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICBmb3IgKGludCBrID0gajsgayA8IGJhc2VQYXJ0aWNsZUFycmF5Lmxlbmd0aDsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFiYXNlUGFydGljbGVBcnJheVtrXS5pc1NraXBwYWJsZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2VWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgbWVzc2FnZSA9ICJGb3VuZCB0cmFpbGluZyBiYXNlIHBhcnRpY2xlcyB0aGF0IGFyZSBub3Qgb3B0aW9uYWwgYW5kIGFyZSBub3QgIiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInJlcHJlc2VudGVkIGluIHRoZSBkZXJpdmVkIGNvbnRlbnQgbW9kZWwuIjsKICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0RGVyaXZlZE1hcHBpbmdFcnJvcihtZXNzYWdlLCBiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVjdXJzZVZhbGlkOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXREZXJpdmVkTWFwcGluZ0Vycm9yKFN0cmluZyBtZXNzYWdlLCBTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIFRoZSBkZXJpdmVkIChyZXN0cmljdGVkKSBjb250ZW50IG1vZGVsIG11c3QgbWF0Y2ggdGhlIGJhc2UgY29udGVudCBtb2RlbCB1bmxlc3MgIgogICAgICAgICAgICAgICAgKyAidGhlIHBhcnQgb2YgdGhlIGJhc2UgY29udGVudCBtb2RlbCB0aGF0IGRvZXMgbm90IG1hdGNoIGlzIG9wdGlvbmFsLiAgQSBtaXNtYXRjaCBmb3VuZCBiZXR3ZWVuIGEgYmFzZSAiICsKICAgICAgICAgICAgICAgIHByaW50UGFydGljbGUoYmFzZU1vZGVsKSArICIgYW5kIGEgZGVyaXZlZCAiICsgcHJpbnRQYXJ0aWNsZShkZXJpdmVkTW9kZWwpICsgIi4gICIgKyBtZXNzYWdlOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gbnNSZWN1cnNlQ2hlY2tDYXJkaW5hbGl0eShTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCwgQ29sbGVjdGlvbiBlcnJvcnMsIFhtbE9iamVjdCBjb250ZXh0KSB7CiAgICAgICAgLy8gbnNSZWN1cnNlQ2hlY2tDYXJkaW5hbGl0eSBpcyBjYWxsZWQgd2hlbjoKICAgICAgICAvLyBiYXNlOiBBTlksIGRlcml2ZWQ6IEFMTAogICAgICAgIC8vIGJhc2U6IEFOWSwgZGVyaXZlZDogQ0hPSUNFCiAgICAgICAgLy8gYmFzZTogQU5ZLCBkZXJpdmVkOiBTRVFVRU5DRQogICAgICAgIGFzc2VydCBiYXNlTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuV0lMRENBUkQ7CiAgICAgICAgYXNzZXJ0IChkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMKQogICAgICAgICAgICAgICAgfHwgKGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0UpCiAgICAgICAgICAgICAgICB8fCAoZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFKTsKICAgICAgICBib29sZWFuIG5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHkgPSB0cnVlOwogICAgICAgIC8vIEZvciBhIGdyb3VwIHBhcnRpY2xlIHRvIGJlIGEgt3ZhbGlkIHJlc3RyaWN0aW9utyBvZiBhIHdpbGRjYXJkIHBhcnRpY2xlIGFsbCBvZiB0aGUgZm9sbG93aW5nIG11c3QgYmUgdHJ1ZToKICAgICAgICAvLyAxIEV2ZXJ5IG1lbWJlciBvZiB0aGUge3BhcnRpY2xlc30gb2YgdGhlIGdyb3VwIGlzIGEgt3ZhbGlkIHJlc3RyaWN0aW9utyBvZiB0aGUgd2lsZGNhcmQgYXMgZGVmaW5lZCBieSBQYXJ0aWNsZSBWYWxpZCAoUmVzdHJpY3Rpb24pICinMy45LjYpLgogICAgICAgIC8vICBOb3RlOiAgbm90IHBvc2l0aXZlIHdoYXQgdGhpcyBtZWFucy4gIEludGVycHJldGluZyB0byBtZWFuIHRoYXQgZXZlcnkgcGFydGljbGUgb2YgdGhlIGdyb3VwIG11c3QgYWRoZXJlIHRvIHdpbGRjYXJkIGRlcml2YXRpb24gcnVsZXMKICAgICAgICAvLyAgICAgICAgIGluIGEgcmVjdXJzaXZlIG1hbm5lcgogICAgICAgIC8vICBMb29wIHRocnUgdGhlIGNoaWxkcmVuIHBhcnRpY2xlcyBvZiB0aGUgZ3JvdXAgYW5kIGludm9rZSB0aGUgYXBwcm9wcmlhdGUgZnVuY3Rpb24gdG8gY2hlY2sgZm9yIHdpbGRjYXJkIHJlc3RyaWN0aW9uIHZhbGlkaXR5CiAgICAgICAgCiAgICAgICAgLy8gQkFVIC0gYW4gZXJyYXRhIHNob3VsZCBiZSBzdWJtaXR0ZWQgb24gdGhpcyBjbGF1c2Ugb2YgdGhlIHNwZWMsIGJlY2F1c2UgdGhlCiAgICAgICAgLy8gc3BlYyBtYWtlcyBubyBzZW5zZSwgYXMgdGhlIHhzdGMgcGFydGljbGVzUjAxMy54c2QgdGVzdCBleGVtcGxpZmllcy4KICAgICAgICAvLyB3aGF0IHdlIF9zaG91bGRfIHNvIGlzIGFuICJhcyBpZiIgb24gdGhlIHdpbGRjYXJkLCBhbGxvd2luZyBpdCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIgogICAgICAgIC8vIGJlZm9yZSByZWN1cnNpbmcKICAgICAgICBTY2hlbWFQYXJ0aWNsZUltcGwgYXNJZlBhcnQgPSBuZXcgU2NoZW1hUGFydGljbGVJbXBsKCk7CiAgICAgICAgYXNJZlBhcnQuc2V0UGFydGljbGVUeXBlKGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSk7CiAgICAgICAgYXNJZlBhcnQuc2V0V2lsZGNhcmRQcm9jZXNzKGJhc2VNb2RlbC5nZXRXaWxkY2FyZFByb2Nlc3MoKSk7CiAgICAgICAgYXNJZlBhcnQuc2V0V2lsZGNhcmRTZXQoYmFzZU1vZGVsLmdldFdpbGRjYXJkU2V0KCkpOwogICAgICAgIGFzSWZQYXJ0LnNldE1pbk9jY3VycyhCaWdJbnRlZ2VyLlpFUk8pOwogICAgICAgIGFzSWZQYXJ0LnNldE1heE9jY3VycyhudWxsKTsKICAgICAgICBhc0lmUGFydC5zZXRUcmFuc2l0aW9uUnVsZXMoYmFzZU1vZGVsLmdldFdpbGRjYXJkU2V0KCksIHRydWUpOwogICAgICAgIGFzSWZQYXJ0LnNldFRyYW5zaXRpb25Ob3RlcyhiYXNlTW9kZWwuZ2V0V2lsZGNhcmRTZXQoKSwgdHJ1ZSk7CgogICAgICAgIFNjaGVtYVBhcnRpY2xlW10gcGFydGljbGVDaGlsZHJlbiA9IGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYXJ0aWNsZUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlIHBhcnRpY2xlID0gcGFydGljbGVDaGlsZHJlbltpXTsKICAgICAgICAgICAgc3dpdGNoIChwYXJ0aWNsZS5nZXRQYXJ0aWNsZVR5cGUoKSkgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGZvciB2YWxpZCBXaWxkY2FyZC9FbGVtZW50IGRlcml2YXRpb24KICAgICAgICAgICAgICAgICAgICBuc1JlY3Vyc2VDaGVja0NhcmRpbmFsaXR5ID0gbnNDb21wYXQoYXNJZlBhcnQsIChTY2hlbWFMb2NhbEVsZW1lbnQpIHBhcnRpY2xlLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDoKICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgdmFsaWQgV2lsZGNhcmQvV2lsZGNhcmQgZGVyaXZhdGlvbgogICAgICAgICAgICAgICAgICAgIG5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHkgPSBuc1N1YnNldChhc0lmUGFydCwgcGFydGljbGUsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQ0hPSUNFOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgdmFsaWQgV2lsZGNhcmQvR3JvdXAgZGVyaXZhdGlvbgogICAgICAgICAgICAgICAgICAgIG5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHkgPSBuc1JlY3Vyc2VDaGVja0NhcmRpbmFsaXR5KGFzSWZQYXJ0LCBkZXJpdmVkTW9kZWwsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gSWYgYW55IHBhcnRpY2xlIGlzIGludmFsaWQgdGhlbiBicmVhayB0aGUgbG9vcAogICAgICAgICAgICBpZiAoIW5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHkpIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyAyIFRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgdGhlIGdyb3VwLCBhcyBkZWZpbmVkIGJ5IEVmZmVjdGl2ZSBUb3RhbCBSYW5nZSAoYWxsIGFuZCBzZXF1ZW5jZSkgKKczLjguNikKICAgICAgICAvLyAoaWYgdGhlIGdyb3VwIGlzIGFsbCBvciBzZXF1ZW5jZSkgb3IgRWZmZWN0aXZlIFRvdGFsIFJhbmdlIChjaG9pY2UpICinMy44LjYpIChpZiBpdCBpcyBjaG9pY2UpIGlzIGEgdmFsaWQKICAgICAgICAvLyByZXN0cmljdGlvbiBvZiBCJ3Mgb2NjdXJyZW5jZSByYW5nZSBhcyBkZWZpbmVkIGJ5IE9jY3VycmVuY2UgUmFuZ2UgT0sgKKczLjkuNikuCgogICAgICAgIGlmIChuc1JlY3Vyc2VDaGVja0NhcmRpbmFsaXR5KSB7CiAgICAgICAgICAgIG5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHkgPSBjaGVja0dyb3VwT2NjdXJyZW5jZU9LKGJhc2VNb2RlbCwgZGVyaXZlZE1vZGVsLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5zUmVjdXJzZUNoZWNrQ2FyZGluYWxpdHk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBjaGVja0dyb3VwT2NjdXJyZW5jZU9LKFNjaGVtYVBhcnRpY2xlIGJhc2VNb2RlbCwgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsLCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpIHsKICAgICAgICBib29sZWFuIGdyb3VwT2NjdXJyZW5jZU9LID0gdHJ1ZTsKICAgICAgICBCaWdJbnRlZ2VyIG1pblJhbmdlID0gQmlnSW50ZWdlci5aRVJPOwogICAgICAgIEJpZ0ludGVnZXIgbWF4UmFuZ2UgPSBCaWdJbnRlZ2VyLlpFUk87CiAgICAgICAgc3dpdGNoIChkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVUeXBlKCkpIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICBtaW5SYW5nZSA9IGdldEVmZmVjdGl2ZU1pblJhbmdlQWxsU2VxKGRlcml2ZWRNb2RlbCk7CiAgICAgICAgICAgICAgICBtYXhSYW5nZSA9IGdldEVmZmVjdGl2ZU1heFJhbmdlQWxsU2VxKGRlcml2ZWRNb2RlbCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBtaW5SYW5nZSA9IGdldEVmZmVjdGl2ZU1pblJhbmdlQ2hvaWNlKGRlcml2ZWRNb2RlbCk7CiAgICAgICAgICAgICAgICBtYXhSYW5nZSA9IGdldEVmZmVjdGl2ZU1heFJhbmdlQ2hvaWNlKGRlcml2ZWRNb2RlbCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIENoZWNrIG1pbiBvY2N1cnMgZm9yIHZhbGlkaXR5CiAgICAgICAgLy8gZGVyaXZlZCBtaW4gb2NjdXJzIGlzIHZhbGlkIGlmIGl0cyB7bWluIG9jY3Vyc30gaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvdGhlcidzIHttaW4gb2NjdXJzfS4KICAgICAgICBpZiAobWluUmFuZ2UuY29tcGFyZVRvKGJhc2VNb2RlbC5nZXRNaW5PY2N1cnMoKSkgPCAwKSB7CiAgICAgICAgICAgIGdyb3VwT2NjdXJyZW5jZU9LID0gZmFsc2U7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEdyb3VwTWluT2NjdXJzRXJyb3IoZGVyaXZlZE1vZGVsLCBiYXNlTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgfQogICAgICAgIC8vIENoZWNrIG1heCBvY2N1cnMgZm9yIHZhbGlkaXR5CiAgICAgICAgLy8gb25lIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIFRoZSBiYXNlIG1vZGVsJ3Mge21heCBvY2N1cnN9IGlzIHVuYm91bmRlZC4KICAgICAgICAvLyBvciBib3RoIHttYXggb2NjdXJzfSBhcmUgbnVtYmVycywgYW5kIHRoZSBwYXJ0aWNsZSdzIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byB0aGUgb3RoZXIncwogICAgICAgIEJpZ0ludGVnZXIgVU5CT1VOREVEID0gbnVsbDsKICAgICAgICBpZiAoYmFzZU1vZGVsLmdldE1heE9jY3VycygpICE9IFVOQk9VTkRFRCkgewogICAgICAgICAgICBpZiAobWF4UmFuZ2UgPT0gVU5CT1VOREVEKSB7CiAgICAgICAgICAgICAgICBncm91cE9jY3VycmVuY2VPSyA9IGZhbHNlOwogICAgICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoZm9ybWF0R3JvdXBNYXhPY2N1cnNFcnJvcihkZXJpdmVkTW9kZWwsIGJhc2VNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlmIChtYXhSYW5nZS5jb21wYXJlVG8oYmFzZU1vZGVsLmdldE1heE9jY3VycygpKSA+IDApIHsKICAgICAgICAgICAgICAgICAgICBncm91cE9jY3VycmVuY2VPSyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdEdyb3VwTWF4T2NjdXJzRXJyb3IoZGVyaXZlZE1vZGVsLCBiYXNlTW9kZWwpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGdyb3VwT2NjdXJyZW5jZU9LOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXRHcm91cE1heE9jY3Vyc0Vycm9yKFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCwgU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsKSB7CiAgICAgICAgcmV0dXJuICJJbnZhbGlkIFJlc3RyaWN0aW9uLiAgVGhlIG1heE9jY3VycyBmb3IgdGhlIGRlcml2ZWQgZ3JvdXAgIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRNb2RlbCkKICAgICAgICAgICAgICAgICsgIiBpcyBncmVhdCB0aGFuIHRoZSBiYXNlIG1heE9jY3VycyBvZiAiCiAgICAgICAgICAgICAgICArIHByaW50TWF4T2NjdXJzKGJhc2VNb2RlbC5nZXRNYXhPY2N1cnMoKSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGZvcm1hdEdyb3VwTWluT2NjdXJzRXJyb3IoU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBUaGUgbWluT2NjdXJzIGZvciB0aGUgZGVyaXZlZCBncm91cCAiCiAgICAgICAgICAgICAgICArIHByaW50UGFydGljbGUoZGVyaXZlZE1vZGVsKQogICAgICAgICAgICAgICAgKyAiIGlzIGxlc3MgdGhhbiB0aGUgYmFzZSBtaW5PY2N1cnMgb2YgIgogICAgICAgICAgICAgICAgKyBiYXNlTW9kZWwuZ2V0TWluT2NjdXJzKCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgQmlnSW50ZWdlciBnZXRFZmZlY3RpdmVNYXhSYW5nZUNob2ljZShTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwpIHsKICAgICAgICBCaWdJbnRlZ2VyIG1heFJhbmdlID0gQmlnSW50ZWdlci5aRVJPOwogICAgICAgIEJpZ0ludGVnZXIgVU5CT1VOREVEID0gbnVsbDsKICAgICAgICAvLyBTY2hlbWEgQ29tcG9uZW50IENvbnN0cmFpbnQ6IEVmZmVjdGl2ZSBUb3RhbCBSYW5nZSAoY2hvaWNlKQogICAgICAgIC8vIFRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgYSBwYXJ0aWNsZSB3aG9zZSB7dGVybX0gaXMgYSBncm91cCB3aG9zZSB7Y29tcG9zaXRvcn0gaXMgY2hvaWNlCiAgICAgICAgLy8gaXMgYSBwYWlyIG9mIG1pbmltdW0gYW5kIG1heGltdW0sIGFzIGZvbGxvd3M6CiAgICAgICAgLy8gTUFYSU1VTQogICAgICAgIC8vIDEpIHVuYm91bmRlZCBpZiB0aGUge21heCBvY2N1cnN9IG9mIGFueSB3aWxkY2FyZCBvciBlbGVtZW50IGRlY2xhcmF0aW9uIHBhcnRpY2xlIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IG9yCiAgICAgICAgLy8gdGhlIG1heGltdW0gcGFydCBvZiB0aGUgZWZmZWN0aXZlIHRvdGFsIHJhbmdlIG9mIGFueSBvZiB0aGUgZ3JvdXAgcGFydGljbGVzIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IGlzCiAgICAgICAgLy8gdW5ib3VuZGVkIChub3RlOiBzZWVtcyB0byBiZSB0aGUgc2FtZSBhcyBNYXggUmFuZ2UgQWxsIG9yIFNlcXVlbmNlKSwKICAgICAgICAvLyBvciAyKSBpZiBhbnkgb2YgdGhvc2UgaXMgbm9uLXplcm8gYW5kIHRoZSB7bWF4IG9jY3Vyc30gb2YgdGhlIHBhcnRpY2xlIGl0c2VsZiBpcyB1bmJvdW5kZWQsCiAgICAgICAgLy8gb3RoZXJ3aXNlIDMpIHRoZSBwcm9kdWN0IG9mIHRoZSBwYXJ0aWNsZSdzIHttYXggb2NjdXJzfSBhbmQgdGhlIG1heGltdW0gb2YgdGhlIHttYXggb2NjdXJzfSBvZiBldmVyeQogICAgICAgIC8vIHdpbGRjYXJkIG9yIGVsZW1lbnQgZGVjbGFyYXRpb24gcGFydGljbGUgaW4gdGhlIGdyb3VwJ3Mge3BhcnRpY2xlc30gYW5kIHRoZSAqbWF4aW11bSogKG5vdGU6IHRoaXMgaXMgdGhlIGRpZmZlcmVuY2UKICAgICAgICAvLyBiZXR3ZWVuIE1heFJhbmdlIENob2ljZSBhbnMgTWF4UmFuZ2UgQWxsIG9yIFNlcXVlbmNlKSBwYXJ0IG9mIHRoZQogICAgICAgIC8vIGVmZmVjdGl2ZSB0b3RhbCByYW5nZSBvZiBlYWNoIG9mIHRoZSBncm91cCBwYXJ0aWNsZXMgaW4gdGhlIGdyb3VwJ3Mge3BhcnRpY2xlc30KICAgICAgICAvLyAob3IgMCBpZiB0aGVyZSBhcmUgbm8ge3BhcnRpY2xlc30pLgoKICAgICAgICBib29sZWFuIG5vblplcm9QYXJ0aWNsZUNoaWxkRm91bmQgPSBmYWxzZTsKICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3Vyc0luV2lsZENhcmRPckVsZW1lbnQgPSBCaWdJbnRlZ2VyLlpFUk87CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnNJbkdyb3VwID0gQmlnSW50ZWdlci5aRVJPOwogICAgICAgIFNjaGVtYVBhcnRpY2xlW10gcGFydGljbGVDaGlsZHJlbiA9IGRlcml2ZWRNb2RlbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYXJ0aWNsZUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlIHBhcnRpY2xlID0gcGFydGljbGVDaGlsZHJlbltpXTsKICAgICAgICAgICAgc3dpdGNoIChwYXJ0aWNsZS5nZXRQYXJ0aWNsZVR5cGUoKSkgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDoKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuRUxFTUVOVDoKICAgICAgICAgICAgICAgICAgICAvLyBpZiB1bmJvdW5kZWQgdGhlbiBtYXhvY2N1cnMgd2lsbCBiZSBudWxsCiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnRpY2xlLmdldE1heE9jY3VycygpID09IFVOQk9VTkRFRCkgewogICAgICAgICAgICAgICAgICAgICAgICBtYXhSYW5nZSA9IFVOQk9VTkRFRDsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFydGljbGUuZ2V0SW50TWF4T2NjdXJzKCkgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzaG93IHRodCBhdCBsZWFzdCBvbmUgbm9uLXplcm8gcGFydGljbGUgaXMgZm91bmQgZm9yIGxhdGVyIHRlc3QKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vblplcm9QYXJ0aWNsZUNoaWxkRm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnRpY2xlLmdldE1heE9jY3VycygpLmNvbXBhcmVUbyhtYXhPY2N1cnNJbldpbGRDYXJkT3JFbGVtZW50KSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnNJbldpbGRDYXJkT3JFbGVtZW50ID0gcGFydGljbGUuZ2V0TWF4T2NjdXJzKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgbWF4UmFuZ2UgPSBnZXRFZmZlY3RpdmVNYXhSYW5nZUFsbFNlcShkZXJpdmVkTW9kZWwpOwogICAgICAgICAgICAgICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBoaWdoZXN0IG1heG9jY3VycyBmb3VuZAogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF4UmFuZ2UuY29tcGFyZVRvKG1heE9jY3Vyc0luR3JvdXApID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzSW5Hcm91cCA9IG1heFJhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgbWF4UmFuZ2UgPSBnZXRFZmZlY3RpdmVNYXhSYW5nZUNob2ljZShkZXJpdmVkTW9kZWwpOwogICAgICAgICAgICAgICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBoaWdoZXN0IG1heG9jY3VycyBmb3VuZAogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF4UmFuZ2UuY29tcGFyZVRvKG1heE9jY3Vyc0luR3JvdXApID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzSW5Hcm91cCA9IG1heFJhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIGlmIGFuIHVuYm91bmRlZCBoYXMgYmVlbiBmb3VuZCB0aGVuIHdlIGFyZSBkb25lCiAgICAgICAgICAgIGlmIChtYXhSYW5nZSA9PSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyAxKSB1bmJvdW5kZWQgaWYgdGhlIHttYXggb2NjdXJzfSBvZiBhbnkgd2lsZGNhcmQgb3IgZWxlbWVudCBkZWNsYXJhdGlvbiBwYXJ0aWNsZSBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfSBvcgogICAgICAgIC8vIHRoZSBtYXhpbXVtIHBhcnQgb2YgdGhlIGVmZmVjdGl2ZSB0b3RhbCByYW5nZSBvZiBhbnkgb2YgdGhlIGdyb3VwIHBhcnRpY2xlcyBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfSBpcwogICAgICAgIC8vIHVuYm91bmRlZAogICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgLy8gMikgaWYgYW55IG9mIHRob3NlIGlzIG5vbi16ZXJvIGFuZCB0aGUge21heCBvY2N1cnN9IG9mIHRoZSBwYXJ0aWNsZSBpdHNlbGYgaXMgdW5ib3VuZGVkCiAgICAgICAgICAgIGlmIChub25aZXJvUGFydGljbGVDaGlsZEZvdW5kICYmIGRlcml2ZWRNb2RlbC5nZXRNYXhPY2N1cnMoKSA9PSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgIG1heFJhbmdlID0gVU5CT1VOREVEOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gMykgdGhlIHByb2R1Y3Qgb2YgdGhlIHBhcnRpY2xlJ3Mge21heCBvY2N1cnN9IGFuZCB0aGUgbWF4aW11bSBvZiB0aGUge21heCBvY2N1cnN9IG9mIGV2ZXJ5CiAgICAgICAgICAgICAgICAvLyB3aWxkY2FyZCBvciBlbGVtZW50IGRlY2xhcmF0aW9uIHBhcnRpY2xlIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IGFuZCB0aGUgKm1heGltdW0qCiAgICAgICAgICAgICAgICAvLyBwYXJ0IG9mIHRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgZWFjaCBvZiB0aGUgZ3JvdXAgcGFydGljbGVzIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9CiAgICAgICAgICAgICAgICBtYXhSYW5nZSA9IGRlcml2ZWRNb2RlbC5nZXRNYXhPY2N1cnMoKS5tdWx0aXBseShtYXhPY2N1cnNJbldpbGRDYXJkT3JFbGVtZW50LmFkZChtYXhPY2N1cnNJbkdyb3VwKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXhSYW5nZTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBCaWdJbnRlZ2VyIGdldEVmZmVjdGl2ZU1heFJhbmdlQWxsU2VxKFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCkgewogICAgICAgIEJpZ0ludGVnZXIgbWF4UmFuZ2UgPSBCaWdJbnRlZ2VyLlpFUk87CiAgICAgICAgQmlnSW50ZWdlciBVTkJPVU5ERUQgPSBudWxsOwogICAgICAgIC8vIFNjaGVtYSBDb21wb25lbnQgQ29uc3RyYWludDogRWZmZWN0aXZlIFRvdGFsIFJhbmdlIChhbGwgYW5kIHNlcXVlbmNlKQogICAgICAgIC8vIFRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgYSBwYXJ0aWNsZSB3aG9zZSB7dGVybX0gaXMgYSBncm91cCB3aG9zZSB7Y29tcG9zaXRvcn0gaXMgYWxsIG9yIHNlcXVlbmNlIGlzIGEKICAgICAgICAvLyBwYWlyIG9mIG1pbmltdW0gYW5kIG1heGltdW0sIGFzIGZvbGxvd3M6CiAgICAgICAgLy8gTUFYSU1VTQogICAgICAgIC8vIDEpIHVuYm91bmRlZCBpZiB0aGUge21heCBvY2N1cnN9IG9mIGFueSB3aWxkY2FyZCBvciBlbGVtZW50IGRlY2xhcmF0aW9uIHBhcnRpY2xlIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IG9yCiAgICAgICAgLy8gdGhlIG1heGltdW0gcGFydCBvZiB0aGUgZWZmZWN0aXZlIHRvdGFsIHJhbmdlIG9mIGFueSBvZiB0aGUgZ3JvdXAgcGFydGljbGVzIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IGlzCiAgICAgICAgLy8gdW5ib3VuZGVkLCBvciAyKSBpZiBhbnkgb2YgdGhvc2UgaXMgbm9uLXplcm8gYW5kIHRoZSB7bWF4IG9jY3Vyc30gb2YgdGhlIHBhcnRpY2xlIGl0c2VsZiBpcyB1bmJvdW5kZWQsIG90aGVyd2lzZQogICAgICAgIC8vIDMpIHRoZSBwcm9kdWN0IG9mIHRoZSBwYXJ0aWNsZSdzIHttYXggb2NjdXJzfSBhbmQgdGhlICpzdW0qIG9mIHRoZSB7bWF4IG9jY3Vyc30gb2YgZXZlcnkgd2lsZGNhcmQgb3IgZWxlbWVudAogICAgICAgIC8vIGRlY2xhcmF0aW9uIHBhcnRpY2xlIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IGFuZCB0aGUgbWF4aW11bSBwYXJ0IG9mIHRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgZWFjaCBvZgogICAgICAgIC8vIHRoZSBncm91cCBwYXJ0aWNsZXMgaW4gdGhlIGdyb3VwJ3Mge3BhcnRpY2xlc30gKG9yIDAgaWYgdGhlcmUgYXJlIG5vIHtwYXJ0aWNsZXN9KS4KCiAgICAgICAgYm9vbGVhbiBub25aZXJvUGFydGljbGVDaGlsZEZvdW5kID0gZmFsc2U7CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnNUb3RhbCA9IEJpZ0ludGVnZXIuWkVSTzsKICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3Vyc0luR3JvdXAgPSBCaWdJbnRlZ2VyLlpFUk87CiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBwYXJ0aWNsZUNoaWxkcmVuID0gZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhcnRpY2xlQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgcGFydGljbGUgPSBwYXJ0aWNsZUNoaWxkcmVuW2ldOwogICAgICAgICAgICBzd2l0Y2ggKHBhcnRpY2xlLmdldFBhcnRpY2xlVHlwZSgpKSB7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgIC8vIGlmIHVuYm91bmRlZCB0aGVuIG1heG9jY3VycyB3aWxsIGJlIG51bGwKICAgICAgICAgICAgICAgICAgICBpZiAocGFydGljbGUuZ2V0TWF4T2NjdXJzKCkgPT0gVU5CT1VOREVEKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG1heFJhbmdlID0gVU5CT1VOREVEOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJ0aWNsZS5nZXRJbnRNYXhPY2N1cnMoKSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNob3cgdGh0IGF0IGxlYXN0IG9uZSBub24temVybyBwYXJ0aWNsZSBpcyBmb3VuZCBmb3IgbGF0ZXIgdGVzdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uWmVyb1BhcnRpY2xlQ2hpbGRGb3VuZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnNUb3RhbCA9IG1heE9jY3Vyc1RvdGFsLmFkZChwYXJ0aWNsZS5nZXRNYXhPY2N1cnMoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgbWF4UmFuZ2UgPSBnZXRFZmZlY3RpdmVNYXhSYW5nZUFsbFNlcShkZXJpdmVkTW9kZWwpOwogICAgICAgICAgICAgICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBoaWdoZXN0IG1heG9jY3VycyBmb3VuZAogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF4UmFuZ2UuY29tcGFyZVRvKG1heE9jY3Vyc0luR3JvdXApID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzSW5Hcm91cCA9IG1heFJhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgbWF4UmFuZ2UgPSBnZXRFZmZlY3RpdmVNYXhSYW5nZUNob2ljZShkZXJpdmVkTW9kZWwpOwogICAgICAgICAgICAgICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBoaWdoZXN0IG1heG9jY3VycyBmb3VuZAogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF4UmFuZ2UuY29tcGFyZVRvKG1heE9jY3Vyc0luR3JvdXApID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzSW5Hcm91cCA9IG1heFJhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIGlmIGFuIHVuYm91bmRlZCBoYXMgYmVlbiBmb3VuZCB0aGVuIHdlIGFyZSBkb25lCiAgICAgICAgICAgIGlmIChtYXhSYW5nZSA9PSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyAxKSB1bmJvdW5kZWQgaWYgdGhlIHttYXggb2NjdXJzfSBvZiBhbnkgd2lsZGNhcmQgb3IgZWxlbWVudCBkZWNsYXJhdGlvbiBwYXJ0aWNsZSBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfSBvcgogICAgICAgIC8vIHRoZSBtYXhpbXVtIHBhcnQgb2YgdGhlIGVmZmVjdGl2ZSB0b3RhbCByYW5nZSBvZiBhbnkgb2YgdGhlIGdyb3VwIHBhcnRpY2xlcyBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfSBpcwogICAgICAgIC8vIHVuYm91bmRlZAogICAgICAgIGlmIChtYXhSYW5nZSAhPSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgLy8gMikgaWYgYW55IG9mIHRob3NlIGlzIG5vbi16ZXJvIGFuZCB0aGUge21heCBvY2N1cnN9IG9mIHRoZSBwYXJ0aWNsZSBpdHNlbGYgaXMgdW5ib3VuZGVkCiAgICAgICAgICAgIGlmIChub25aZXJvUGFydGljbGVDaGlsZEZvdW5kICYmIGRlcml2ZWRNb2RlbC5nZXRNYXhPY2N1cnMoKSA9PSBVTkJPVU5ERUQpIHsKICAgICAgICAgICAgICAgIG1heFJhbmdlID0gVU5CT1VOREVEOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gMykgdGhlIHByb2R1Y3Qgb2YgdGhlIHBhcnRpY2xlJ3Mge21heCBvY2N1cnN9IGFuZCB0aGUgc3VtIG9mIHRoZSB7bWF4IG9jY3Vyc30gb2YgZXZlcnkgd2lsZGNhcmQgb3IgZWxlbWVudAogICAgICAgICAgICAgICAgLy8gZGVjbGFyYXRpb24gcGFydGljbGUgaW4gdGhlIGdyb3VwJ3Mge3BhcnRpY2xlc30gYW5kIHRoZSBtYXhpbXVtIHBhcnQgb2YgdGhlIGVmZmVjdGl2ZSB0b3RhbCByYW5nZSBvZiBlYWNoIG9mCiAgICAgICAgICAgICAgICAvLyB0aGUgZ3JvdXAgcGFydGljbGVzIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9CiAgICAgICAgICAgICAgICBtYXhSYW5nZSA9IGRlcml2ZWRNb2RlbC5nZXRNYXhPY2N1cnMoKS5tdWx0aXBseShtYXhPY2N1cnNUb3RhbC5hZGQobWF4T2NjdXJzSW5Hcm91cCkpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbWF4UmFuZ2U7CgogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIEJpZ0ludGVnZXIgZ2V0RWZmZWN0aXZlTWluUmFuZ2VDaG9pY2UoU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsKSB7CiAgICAgICAgLy8gU2NoZW1hIENvbXBvbmVudCBDb25zdHJhaW50OiBFZmZlY3RpdmUgVG90YWwgUmFuZ2UgKGNob2ljZSkKICAgICAgICAvLyBUaGUgZWZmZWN0aXZlIHRvdGFsIHJhbmdlIG9mIGEgcGFydGljbGUgd2hvc2Uge3Rlcm19IGlzIGEgZ3JvdXAgd2hvc2Uge2NvbXBvc2l0b3J9IGlzIGNob2ljZSBpcyBhIHBhaXIgb2YKICAgICAgICAvLyBtaW5pbXVtIGFuZCBtYXhpbXVtLCBhcyBmb2xsb3dzOgogICAgICAgIC8vIE1JTklNVU0KICAgICAgICAvLyBUaGUgcHJvZHVjdCBvZiB0aGUgcGFydGljbGUncyB7bWluIG9jY3Vyc30KICAgICAgICAvLyBhbmQgdGhlICptaW5pbXVtKiBvZiB0aGUge21pbiBvY2N1cnN9IG9mIGV2ZXJ5IHdpbGRjYXJkIG9yIGVsZW1lbnQKICAgICAgICAvLyBkZWNsYXJhdGlvbiBwYXJ0aWNsZSBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfSBhbmQgdGhlIG1pbmltdW0gcGFydCBvZiB0aGUgZWZmZWN0aXZlIHRvdGFsIHJhbmdlIG9mIGVhY2ggb2YKICAgICAgICAvLyB0aGUgZ3JvdXAgcGFydGljbGVzIGluIHRoZSBncm91cCdzIHtwYXJ0aWNsZXN9IChvciAwIGlmIHRoZXJlIGFyZSBubyB7cGFydGljbGVzfSkuCiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBwYXJ0aWNsZUNoaWxkcmVuID0gZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICBpZiAocGFydGljbGVDaGlsZHJlbi5sZW5ndGggPT0gMCkKICAgICAgICAgICAgcmV0dXJuIEJpZ0ludGVnZXIuWkVSTzsKICAgICAgICBCaWdJbnRlZ2VyIG1pblJhbmdlID0gbnVsbDsKICAgICAgICAvLyBnZXQgdGhlIG1pbmltdW0gb2YgZXZlcnkgd2lsZGNhcmQgb3IgZWxlbWVudAogICAgICAgIC8vIHRvdGFsIHVwIHRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2UgZm9yIGVhY2ggZ3JvdXAKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhcnRpY2xlQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgcGFydGljbGUgPSBwYXJ0aWNsZUNoaWxkcmVuW2ldOwogICAgICAgICAgICBzd2l0Y2ggKHBhcnRpY2xlLmdldFBhcnRpY2xlVHlwZSgpKSB7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgIGlmIChtaW5SYW5nZSA9PSBudWxsIHx8IG1pblJhbmdlLmNvbXBhcmVUbyhwYXJ0aWNsZS5nZXRNaW5PY2N1cnMoKSkgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG1pblJhbmdlID0gcGFydGljbGUuZ2V0TWluT2NjdXJzKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgICAgIEJpZ0ludGVnZXIgbXJzID0gZ2V0RWZmZWN0aXZlTWluUmFuZ2VBbGxTZXEoZGVyaXZlZE1vZGVsKTsKICAgICAgICAgICAgICAgICAgICBpZiAobWluUmFuZ2UgPT0gbnVsbCB8fCBtaW5SYW5nZS5jb21wYXJlVG8obXJzKSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgbWluUmFuZ2UgPSBtcnM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgQmlnSW50ZWdlciBtcmMgPSBnZXRFZmZlY3RpdmVNaW5SYW5nZUNob2ljZShkZXJpdmVkTW9kZWwpOwogICAgICAgICAgICAgICAgICAgIGlmIChtaW5SYW5nZSA9PSBudWxsIHx8IG1pblJhbmdlLmNvbXBhcmVUbyhtcmMpID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBtaW5SYW5nZSA9IG1yYzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKG1pblJhbmdlID09IG51bGwpCiAgICAgICAgICAgIG1pblJhbmdlID0gQmlnSW50ZWdlci5aRVJPOwoKICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIHRvdGFsCiAgICAgICAgbWluUmFuZ2UgPSBkZXJpdmVkTW9kZWwuZ2V0TWluT2NjdXJzKCkubXVsdGlwbHkobWluUmFuZ2UpOwogICAgICAgIHJldHVybiBtaW5SYW5nZTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBCaWdJbnRlZ2VyIGdldEVmZmVjdGl2ZU1pblJhbmdlQWxsU2VxKFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRNb2RlbCkgewogICAgICAgIEJpZ0ludGVnZXIgbWluUmFuZ2UgPSBCaWdJbnRlZ2VyLlpFUk87CiAgICAgICAgLy8gU2NoZW1hIENvbXBvbmVudCBDb25zdHJhaW50OiBFZmZlY3RpdmUgVG90YWwgUmFuZ2UgKGFsbCBhbmQgc2VxdWVuY2UpCiAgICAgICAgLy8gVGhlIGVmZmVjdGl2ZSB0b3RhbCByYW5nZSBvZiBhIHBhcnRpY2xlIHdob3NlIHt0ZXJtfSBpcyBhIGdyb3VwIHdob3NlIHtjb21wb3NpdG9yfSBpcyBhbGwgb3Igc2VxdWVuY2UgaXMgYQogICAgICAgIC8vIHBhaXIgb2YgbWluaW11bSBhbmQgbWF4aW11bSwgYXMgZm9sbG93czoKICAgICAgICAvLyBNSU5JTVVNCiAgICAgICAgLy8gVGhlIHByb2R1Y3Qgb2YgdGhlIHBhcnRpY2xlJ3Mge21pbiBvY2N1cnN9CiAgICAgICAgLy8gYW5kIHRoZSAqc3VtKiBvZiB0aGUge21pbiBvY2N1cnN9IG9mIGV2ZXJ5IHdpbGRjYXJkIG9yIGVsZW1lbnQKICAgICAgICAvLyBkZWNsYXJhdGlvbiBwYXJ0aWNsZSBpbiB0aGUgZ3JvdXAncyB7cGFydGljbGVzfQogICAgICAgIC8vIGFuZCB0aGUgbWluaW11bSBwYXJ0IG9mIHRoZSBlZmZlY3RpdmUgdG90YWwgcmFuZ2Ugb2YgZWFjaAogICAgICAgIC8vIG9mIHRoZSBncm91cCBwYXJ0aWNsZXMgaW4gdGhlIGdyb3VwJ3Mge3BhcnRpY2xlc30gKG9yIDAgaWYgdGhlcmUgYXJlIG5vIHtwYXJ0aWNsZXN9KS4KICAgICAgICBTY2hlbWFQYXJ0aWNsZVtdIHBhcnRpY2xlQ2hpbGRyZW4gPSBkZXJpdmVkTW9kZWwuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgIEJpZ0ludGVnZXIgcGFydGljbGVUb3RhbE1pbk9jY3VycyA9IEJpZ0ludGVnZXIuWkVSTzsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhcnRpY2xlQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGUgcGFydGljbGUgPSBwYXJ0aWNsZUNoaWxkcmVuW2ldOwogICAgICAgICAgICBzd2l0Y2ggKHBhcnRpY2xlLmdldFBhcnRpY2xlVHlwZSgpKSB7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgICAgIHBhcnRpY2xlVG90YWxNaW5PY2N1cnMgPSBwYXJ0aWNsZVRvdGFsTWluT2NjdXJzLmFkZChwYXJ0aWNsZS5nZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICAgICAgcGFydGljbGVUb3RhbE1pbk9jY3VycyA9IHBhcnRpY2xlVG90YWxNaW5PY2N1cnMuYWRkKGdldEVmZmVjdGl2ZU1pblJhbmdlQWxsU2VxKGRlcml2ZWRNb2RlbCkpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgcGFydGljbGVUb3RhbE1pbk9jY3VycyA9IHBhcnRpY2xlVG90YWxNaW5PY2N1cnMuYWRkKGdldEVmZmVjdGl2ZU1pblJhbmdlQ2hvaWNlKGRlcml2ZWRNb2RlbCkpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBtaW5SYW5nZSA9IGRlcml2ZWRNb2RlbC5nZXRNaW5PY2N1cnMoKS5tdWx0aXBseShwYXJ0aWNsZVRvdGFsTWluT2NjdXJzKTsKCiAgICAgICAgcmV0dXJuIG1pblJhbmdlOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gbnNTdWJzZXQoU2NoZW1hUGFydGljbGUgYmFzZU1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkTW9kZWwsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgewogICAgICAgIC8vIG5zU3Vic2V0IGlzIGNhbGxlZCB3aGVuIGJhc2U6IEFOWSwgZGVyaXZlZDogQU5ZCiAgICAgICAgYXNzZXJ0IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDsKICAgICAgICBhc3NlcnQgZGVyaXZlZE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOwogICAgICAgIGJvb2xlYW4gbnNTdWJzZXQgPSBmYWxzZTsKICAgICAgICAvLyBGb3IgYSB3aWxkY2FyZCBwYXJ0aWNsZSB0byBiZSBhILd2YWxpZCByZXN0cmljdGlvbrcgb2YgYW5vdGhlciB3aWxkY2FyZCBwYXJ0aWNsZSBhbGwgb2YgdGhlIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgLy8gMSBSJ3Mgb2NjdXJyZW5jZSByYW5nZSBtdXN0IGJlIGEgdmFsaWQgcmVzdHJpY3Rpb24gb2YgQidzIG9jY3VycmVuY2UgcmFuZ2UgYXMgZGVmaW5lZCBieSBPY2N1cnJlbmNlIFJhbmdlIE9LICinMy45LjYpLgogICAgICAgIGlmIChvY2N1cnJlbmNlUmFuZ2VPSyhiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCwgZXJyb3JzLCBjb250ZXh0KSkgewogICAgICAgICAgICAvLyAyIFIncyB7bmFtZXNwYWNlIGNvbnN0cmFpbnR9IG11c3QgYmUgYW4gaW50ZW5zaW9uYWwgc3Vic2V0IG9mIEIncyB7bmFtZXNwYWNlIGNvbnN0cmFpbnR9IGFzIGRlZmluZWQKICAgICAgICAgICAgLy8gYnkgV2lsZGNhcmQgU3Vic2V0ICinMy4xMC42KS4KICAgICAgICAgICAgaWYgKGJhc2VNb2RlbC5nZXRXaWxkY2FyZFNldCgpLmludmVyc2UoKS5pc0Rpc2pvaW50KGRlcml2ZWRNb2RlbC5nZXRXaWxkY2FyZFNldCgpKSkgewogICAgICAgICAgICAgICAgbnNTdWJzZXQgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgbnNTdWJzZXQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE5TSXNOb3RTdWJzZXRFcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5zU3Vic2V0ID0gZmFsc2U7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE5TSXNOb3RTdWJzZXRFcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICB9CgoKICAgICAgICByZXR1cm4gbnNTdWJzZXQ7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBuc0NvbXBhdChTY2hlbWFQYXJ0aWNsZSBiYXNlTW9kZWwsIFNjaGVtYUxvY2FsRWxlbWVudCBkZXJpdmVkRWxlbWVudCwgQ29sbGVjdGlvbiBlcnJvcnMsIFhtbE9iamVjdCBjb250ZXh0KSB7CiAgICAgICAgLy8gbnNDb21wYXQgaXMgY2FsbGVkIHdoZW4gYmFzZTogQU5ZLCBkZXJpdmVkOiBFTEVNRU5UCiAgICAgICAgYXNzZXJ0IGJhc2VNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDsKICAgICAgICBib29sZWFuIG5zQ29tcGF0ID0gZmFsc2U7CiAgICAgICAgLy8gRm9yIGFuIGVsZW1lbnQgZGVjbGFyYXRpb24gcGFydGljbGUgdG8gYmUgYSC3dmFsaWQgcmVzdHJpY3Rpb263IG9mIGEgd2lsZGNhcmQgcGFydGljbGUgYWxsIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIDEgVGhlIGVsZW1lbnQgZGVjbGFyYXRpb24ncyB7dGFyZ2V0IG5hbWVzcGFjZX0gaXMgt3ZhbGlktyB3aXRoIHJlc3BlY3QgdG8gdGhlIHdpbGRjYXJkJ3Mge25hbWVzcGFjZSBjb25zdHJhaW50fQogICAgICAgIC8vIGFzIGRlZmluZWQgYnkgV2lsZGNhcmQgYWxsb3dzIE5hbWVzcGFjZSBOYW1lICinMy4xMC40KS4KICAgICAgICBpZiAoYmFzZU1vZGVsLmdldFdpbGRjYXJkU2V0KCkuY29udGFpbnMoZGVyaXZlZEVsZW1lbnQuZ2V0TmFtZSgpKSkgewogICAgICAgICAgICAvLyAyIFIncyBvY2N1cnJlbmNlIHJhbmdlIGlzIGEgdmFsaWQgcmVzdHJpY3Rpb24gb2YgQidzIG9jY3VycmVuY2UgcmFuZ2UgYXMgZGVmaW5lZCBieSBPY2N1cnJlbmNlIFJhbmdlIE9LICinMy45LjYpLgogICAgICAgICAgICBpZiAob2NjdXJyZW5jZVJhbmdlT0soYmFzZU1vZGVsLCAoU2NoZW1hUGFydGljbGUpIGRlcml2ZWRFbGVtZW50LCBlcnJvcnMsIGNvbnRleHQpKSB7CiAgICAgICAgICAgICAgICBuc0NvbXBhdCA9IHRydWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRPY2N1cmVuY2VSYW5nZU1pbkVycm9yKGJhc2VNb2RlbCwgKFNjaGVtYVBhcnRpY2xlKSBkZXJpdmVkRWxlbWVudCksIGNvbnRleHQpKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5zQ29tcGF0ID0gZmFsc2U7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE5TSXNOb3RTdWJzZXRFcnJvcihiYXNlTW9kZWwsIChTY2hlbWFQYXJ0aWNsZSkgZGVyaXZlZEVsZW1lbnQpLCBjb250ZXh0KSk7CiAgICAgICAgfQoKCiAgICAgICAgcmV0dXJuIG5zQ29tcGF0OwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXROU0lzTm90U3Vic2V0RXJyb3IoU2NoZW1hUGFydGljbGUgYmFzZVBhcnRpY2xlLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkUGFydGljbGUpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uIFRoZSBuYW1lc3BhY2Uocykgb2YgdGhlIGRlcml2ZWQgZmllbGQ6ICIgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRQYXJ0aWNsZSkKICAgICAgICAgICAgICAgICsgIiBhcmUgbm90IGEgc3Vic2V0IG9mIHRoZSBuYW1lc3BhY2Uocykgb2YgdGhlIGJhc2UgZmllbGQ6ICIgKyBwcmludFBhcnRpY2xlKGJhc2VQYXJ0aWNsZSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGZvcm1hdEludmFsaWRDb21iaW5hdGlvbkVycm9yKFNjaGVtYVBhcnRpY2xlIGJhc2VNb2RlbCwgU2NoZW1hUGFydGljbGUgZGVyaXZlZE1vZGVsKSB7CiAgICAgICAgcmV0dXJuICJJbnZhbGlkIFJlc3RyaWN0aW9uLiAgVGhlIGRlcml2ZWQgY29udGVudCBtb2RlbCAiCiAgICAgICAgICAgICAgICArIHByaW50UGFydGljbGUoZGVyaXZlZE1vZGVsKQogICAgICAgICAgICAgICAgKyAiIGNhbm5vdCByZXN0cmljdCBiYXNlIGNvbnRlbnQgbW9kZWwgIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGJhc2VNb2RlbCk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBuYW1lQW5kVHlwZU9LKFNjaGVtYUxvY2FsRWxlbWVudCBiYXNlRWxlbWVudCwgU2NoZW1hTG9jYWxFbGVtZW50IGRlcml2ZWRFbGVtZW50LCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpIHsKICAgICAgICAvLyBuYW1lQW5kVHlwZU9LIGNhbGxlZCB3aGVuIGJhc2U6IEVMRU1FTlQgYW5kIGRlcml2ZWQ6IEVMRU1FTlQKICAgICAgICBib29sZWFuIG5hbWVBbmRUeXBlT0sgPSBmYWxzZTsKICAgICAgICAvLyBTY2hlbWEgQ29tcG9uZW50IENvbnN0cmFpbnQ6IFBhcnRpY2xlIFJlc3RyaWN0aW9uIE9LIChFbHQ6RWx0IC0tIE5hbWVBbmRUeXBlT0spCiAgICAgICAgLy8gMSBUaGUgZGVjbGFyYXRpb25zJyB7bmFtZX1zIGFuZCB7dGFyZ2V0IG5hbWVzcGFjZX1zIGFyZSB0aGUgc2FtZS4KICAgICAgICBpZiAoKChTY2hlbWFQYXJ0aWNsZSliYXNlRWxlbWVudCkuY2FuU3RhcnRXaXRoRWxlbWVudChkZXJpdmVkRWxlbWVudC5nZXROYW1lKCkpKSB7CiAgICAgICAgICAgIC8vIDIgRWl0aGVyIEIncyB7bmlsbGFibGV9IGlzIHRydWUgb3IgUidzIHtuaWxsYWJsZX0gaXMgZmFsc2UuCiAgICAgICAgICAgIGlmIChiYXNlRWxlbWVudC5pc05pbGxhYmxlKCkgfHwgIWRlcml2ZWRFbGVtZW50LmlzTmlsbGFibGUoKSkgewogICAgICAgICAgICAgICAgLy8gMyBSJ3Mgb2NjdXJyZW5jZSByYW5nZSBpcyBhIHZhbGlkIHJlc3RyaWN0aW9uIG9mIEIncyBvY2N1cnJlbmNlIHJhbmdlIGFzIGRlZmluZWQgYnkgT2NjdXJyZW5jZSBSYW5nZSBPSyAopzMuOS42KS4KICAgICAgICAgICAgICAgIGlmIChvY2N1cnJlbmNlUmFuZ2VPSygoU2NoZW1hUGFydGljbGUpIGJhc2VFbGVtZW50LCAoU2NoZW1hUGFydGljbGUpIGRlcml2ZWRFbGVtZW50LCBlcnJvcnMsIGNvbnRleHQpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gNCBlaXRoZXIgQidzIGRlY2xhcmF0aW9uJ3Mge3ZhbHVlIGNvbnN0cmFpbnR9IGlzIGFic2VudCwgb3IgaXMgbm90IGZpeGVkLAogICAgICAgICAgICAgICAgICAgIC8vIG9yIFIncyBkZWNsYXJhdGlvbidzIHt2YWx1ZSBjb25zdHJhaW50fSBpcyBmaXhlZCB3aXRoIHRoZSBzYW1lIHZhbHVlLgogICAgICAgICAgICAgICAgICAgIG5hbWVBbmRUeXBlT0sgPSBjaGVja0ZpeGVkKGJhc2VFbGVtZW50LCBkZXJpdmVkRWxlbWVudCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICBpZiAobmFtZUFuZFR5cGVPSykgewogICAgICAgICAgICAgICAgICAgICAgICAvLyA1IFIncyBkZWNsYXJhdGlvbidzIHtpZGVudGl0eS1jb25zdHJhaW50IGRlZmluaXRpb25zfSBpcyBhIHN1YnNldCBvZiBCJ3MgZGVjbGFyYXRpb24ncyB7aWRlbnRpdHktY29uc3RyYWludCBkZWZpbml0aW9uc30sIGlmIGFueS4KICAgICAgICAgICAgICAgICAgICAgICAgbmFtZUFuZFR5cGVPSyA9IGNoZWNrSWRlbnRpdHlDb25zdHJhaW50cyhiYXNlRWxlbWVudCwgZGVyaXZlZEVsZW1lbnQsIGVycm9ycywgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYW1lQW5kVHlwZU9LKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA3IFIncyB7dHlwZSBkZWZpbml0aW9ufSBpcyB2YWxpZGx5IGRlcml2ZWQgZ2l2ZW4ge2V4dGVuc2lvbiwgbGlzdCwgdW5pb259IGZyb20gQidzIHt0eXBlIGRlZmluaXRpb259IGFzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWZpbmVkIGJ5IFR5cGUgRGVyaXZhdGlvbiBPSyAoQ29tcGxleCkgKKczLjQuNikgb3IgVHlwZSBEZXJpdmF0aW9uIE9LIChTaW1wbGUpICinMy4xNC42KSwgYXMgYXBwcm9wcmlhdGUuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lQW5kVHlwZU9LID0gdHlwZURlcml2YXRpb25PSyhiYXNlRWxlbWVudC5nZXRUeXBlKCksIGRlcml2ZWRFbGVtZW50LmdldFR5cGUoKSwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYW1lQW5kVHlwZU9LKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gNiBSJ3MgZGVjbGFyYXRpb24ncyB7ZGlzYWxsb3dlZCBzdWJzdGl0dXRpb25zfSBpcyBhIHN1cGVyc2V0IG9mIEIncyBkZWNsYXJhdGlvbidzIHtkaXNhbGxvd2VkIHN1YnN0aXR1dGlvbnN9LgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVBbmRUeXBlT0sgPSBibG9ja1NldE9LKGJhc2VFbGVtZW50LCBkZXJpdmVkRWxlbWVudCwgZXJyb3JzLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbmFtZUFuZFR5cGVPSzsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBibG9ja1NldE9LKFNjaGVtYUxvY2FsRWxlbWVudCBiYXNlRWxlbWVudCwgU2NoZW1hTG9jYWxFbGVtZW50IGRlcml2ZWRFbGVtZW50LCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpCiAgICB7CiAgICAgICAgaWYgKGJhc2VFbGVtZW50LmJsb2NrUmVzdHJpY3Rpb24oKSAmJiAhZGVyaXZlZEVsZW1lbnQuYmxvY2tSZXN0cmljdGlvbigpKQogICAgICAgIHsKICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoIlJlc3RyaWN0aW9uIEludmFsaWQuICBEZXJpdmVkICIgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSlkZXJpdmVkRWxlbWVudCkgKyAiIGRvZXMgbm90IGJsb2NrIHJlc3RyaWN0aW9uIGFzIGRvZXMgdGhlIGJhc2UgIiArIHByaW50UGFydGljbGUoKFNjaGVtYVBhcnRpY2xlKWJhc2VFbGVtZW50KSwgY29udGV4dCkpOwogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmIChiYXNlRWxlbWVudC5ibG9ja0V4dGVuc2lvbigpICYmICFkZXJpdmVkRWxlbWVudC5ibG9ja0V4dGVuc2lvbigpKQogICAgICAgIHsKICAgICAgICAgICAgZXJyb3JzLmFkZChYbWxFcnJvci5mb3JPYmplY3QoIlJlc3RyaWN0aW9uIEludmFsaWQuICBEZXJpdmVkICIgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSlkZXJpdmVkRWxlbWVudCkgKyAiIGRvZXMgbm90IGJsb2NrIGV4dGVuc2lvbiBhcyBkb2VzIHRoZSBiYXNlICIgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSliYXNlRWxlbWVudCksIGNvbnRleHQpKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoYmFzZUVsZW1lbnQuYmxvY2tTdWJzdGl0dXRpb24oKSAmJiAhZGVyaXZlZEVsZW1lbnQuYmxvY2tTdWJzdGl0dXRpb24oKSkKICAgICAgICB7CiAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KCJSZXN0cmljdGlvbiBJbnZhbGlkLiAgRGVyaXZlZCAiICsgcHJpbnRQYXJ0aWNsZSgoU2NoZW1hUGFydGljbGUpZGVyaXZlZEVsZW1lbnQpICsgIiBkb2VzIG5vdCBibG9jayBzdWJzdGl0dXRpb24gYXMgZG9lcyB0aGUgYmFzZSAiICsgcHJpbnRQYXJ0aWNsZSgoU2NoZW1hUGFydGljbGUpYmFzZUVsZW1lbnQpLCBjb250ZXh0KSk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7ICAgIAogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gdHlwZURlcml2YXRpb25PSyhTY2hlbWFUeXBlIGJhc2VUeXBlLCBTY2hlbWFUeXBlIGRlcml2ZWRUeXBlLCBDb2xsZWN0aW9uIGVycm9ycywgWG1sT2JqZWN0IGNvbnRleHQpIHsKICAgICAgICBib29sZWFuIHR5cGVEZXJpdmF0aW9uT0sgPSBmYWxzZTsKICAgICAgICAvLyAxIElmIEIgYW5kIEQgYXJlIG5vdCB0aGUgc2FtZSB0eXBlIGRlZmluaXRpb24sIHRoZW4gdGhlIHtkZXJpdmF0aW9uIG1ldGhvZH0gb2YgRCBtdXN0IG5vdCBiZSBpbiB0aGUgc3Vic2V0LgogICAgICAgIC8vIDIgT25lIG9mIHRoZSBmb2xsb3dpbmcgbXVzdCBiZSB0cnVlOgogICAgICAgIC8vIDIuMSBCIGFuZCBEIG11c3QgYmUgdGhlIHNhbWUgdHlwZSBkZWZpbml0aW9uLgogICAgICAgIC8vIDIuMiBCIG11c3QgYmUgRCdzIHtiYXNlIHR5cGUgZGVmaW5pdGlvbn0uCiAgICAgICAgLy8gMi4zIEFsbCBvZiB0aGUgZm9sbG93aW5nIG11c3QgYmUgdHJ1ZToKICAgICAgICAvLyAyLjMuMSBEJ3Mge2Jhc2UgdHlwZSBkZWZpbml0aW9ufSBtdXN0IG5vdCBiZSB0aGUgt3VyLXR5cGUgZGVmaW5pdGlvbrcuCiAgICAgICAgLy8gMi4zLjIgVGhlIGFwcHJvcHJpYXRlIGNhc2UgYW1vbmcgdGhlIGZvbGxvd2luZyBtdXN0IGJlIHRydWU6CiAgICAgICAgLy8gMi4zLjIuMSBJZiBEJ3Mge2Jhc2UgdHlwZSBkZWZpbml0aW9ufSBpcyBjb21wbGV4LCB0aGVuIGl0IG11c3QgYmUgdmFsaWRseSBkZXJpdmVkIGZyb20gQiBnaXZlbiB0aGUgc3Vic2V0IGFzIGRlZmluZWQgYnkgdGhpcyBjb25zdHJhaW50LgogICAgICAgIC8vIDIuMy4yLjIgSWYgRCdzIHtiYXNlIHR5cGUgZGVmaW5pdGlvbn0gaXMgc2ltcGxlLCB0aGVuIGl0IG11c3QgYmUgdmFsaWRseSBkZXJpdmVkIGZyb20gQiBnaXZlbiB0aGUgc3Vic2V0IGFzIGRlZmluZWQgaW4gVHlwZSBEZXJpdmF0aW9uIE9LIChTaW1wbGUpICinMy4xNC42KS4KICAgICAgICAvLyAgIFRoaXMgbGluZSB3aWxsIGNoZWNrIGlmIGRlcml2ZWRUeXBlIGlzIGEgc3ViVHlwZSBvZiBiYXNlVHlwZSAoc2hvdWxkIGhhbmRsZSBhbGwgb2YgdGhlIDIueHggY2hlY2tzIGFib3ZlKQogICAgICAgIGlmIChiYXNlVHlwZS5pc0Fzc2lnbmFibGVGcm9tKGRlcml2ZWRUeXBlKSkgewogICAgICAgICAgICAvLyBPayBkZXJpdmVkIHR5cGUgaXMgc3VidHlwZSBidXQgbmVlZCB0byBtYWtlIHN1cmUgdGhhdCBhbGwgb2YgdGhlIGRlcml2YXRpb25zIGJldHdlZW4gdGhlIHR3byB0eXBlcyBhcmUgYnkKICAgICAgICAgICAgLy8gUmVzdHJpY3Rpb24uCiAgICAgICAgICAgIHR5cGVEZXJpdmF0aW9uT0sgPSBjaGVja0FsbERlcml2YXRpb25zRm9yUmVzdHJpY3Rpb24oYmFzZVR5cGUsIGRlcml2ZWRUeXBlLCBlcnJvcnMsIGNvbnRleHQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIGRlcml2ZWQgdHlwZSBpcyBub3QgYSBzdWItdHlwZSBvZiBiYXNlIHR5cGUKICAgICAgICAgICAgdHlwZURlcml2YXRpb25PSyA9IGZhbHNlOwogICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXREZXJpdmVkVHlwZU5vdFN1YlR5cGVFcnJvcihiYXNlVHlwZSwgZGVyaXZlZFR5cGUpLCBjb250ZXh0KSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHlwZURlcml2YXRpb25PSzsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0RGVyaXZlZFR5cGVOb3RTdWJUeXBlRXJyb3IoU2NoZW1hVHlwZSBiYXNlVHlwZSwgU2NoZW1hVHlwZSBkZXJpdmVkVHlwZSkgewogICAgICAgIHJldHVybiAiUmVzdHJpY3Rpb24gSW52YWxpZC4gIERlcml2ZWQgVHlwZTogIiArIHByaW50VHlwZShkZXJpdmVkVHlwZSkgKyAiIGlzIG5vdCBhIHN1Yi10eXBlIG9mIEJhc2UgVHlwZTogIiArIHByaW50VHlwZShiYXNlVHlwZSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBjaGVja0FsbERlcml2YXRpb25zRm9yUmVzdHJpY3Rpb24oU2NoZW1hVHlwZSBiYXNlVHlwZSwgU2NoZW1hVHlwZSBkZXJpdmVkVHlwZSwgQ29sbGVjdGlvbiBlcnJvcnMsIFhtbE9iamVjdCBjb250ZXh0KSB7CgogICAgICAgIGJvb2xlYW4gYWxsRGVyaXZhdGlvbnNBcmVSZXN0cmljdGlvbnMgPSB0cnVlOwogICAgICAgIFNjaGVtYVR5cGUgY3VycmVudFR5cGUgPSBkZXJpdmVkVHlwZTsKICAgICAgICAvLyBydW4gdXAgdGhlIHR5cGVzIGhpZXJhcmNoeSBmcm9tIGRlcml2ZWQgVHlwZSB0byBiYXNlIFR5cGUgYW5kIG1ha2Ugc3VyZSB0aGF0IGFsbCBhcmUgZGVyaXZlZCBieQogICAgICAgIC8vICAgcmVzdHJpY3Rpb24uICBJZiBhbnkgYXJlIG5vdCB0aGVuIHRoaXMgaXMgbm90IGEgdmFsaWQgcmVzdHJpY3Rpb24uCiAgICAgICAgd2hpbGUgKCFiYXNlVHlwZS5lcXVhbHMoY3VycmVudFR5cGUpKSB7CiAgICAgICAgICAgIGlmIChjdXJyZW50VHlwZS5nZXREZXJpdmF0aW9uVHlwZSgpID09IFNjaGVtYVR5cGUuRFRfUkVTVFJJQ1RJT04pIHsKICAgICAgICAgICAgICAgIGN1cnJlbnRUeXBlID0gY3VycmVudFR5cGUuZ2V0QmFzZVR5cGUoKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGFsbERlcml2YXRpb25zQXJlUmVzdHJpY3Rpb25zID0gZmFsc2U7CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRBbGxEZXJpdmF0aW9uc0FyZU5vdFJlc3RyaWN0aW9uc0Vycm9yKGJhc2VUeXBlLCBkZXJpdmVkVHlwZSwgY3VycmVudFR5cGUpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gYWxsRGVyaXZhdGlvbnNBcmVSZXN0cmljdGlvbnM7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGZvcm1hdEFsbERlcml2YXRpb25zQXJlTm90UmVzdHJpY3Rpb25zRXJyb3IoU2NoZW1hVHlwZSBiYXNlVHlwZSwgU2NoZW1hVHlwZSBkZXJpdmVkVHlwZSwgU2NoZW1hVHlwZSBjdXJyZW50VHlwZSkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIFRoZSB0eXBlICIgKyBwcmludFR5cGUoZGVyaXZlZFR5cGUpICsgIiBkZXJpdmVkIGZyb20gYmFzZSB0eXBlICIKICAgICAgICAgICAgICAgICsgcHJpbnRUeXBlKGJhc2VUeXBlKSArICIgaGFzIGFuIGludGVybWVkaWFyeSB0eXBlICIgKyBwcmludFR5cGUoY3VycmVudFR5cGUpCiAgICAgICAgICAgICAgICArICJ0aGF0IGlzIG5vdCBkZXJpdmVkIGJ5IHJlc3RyaWN0aW9uLiI7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBjaGVja0lkZW50aXR5Q29uc3RyYWludHMoU2NoZW1hTG9jYWxFbGVtZW50IGJhc2VFbGVtZW50LCBTY2hlbWFMb2NhbEVsZW1lbnQgZGVyaXZlZEVsZW1lbnQsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgewogICAgICAgIC8vIDUgUidzIGRlY2xhcmF0aW9uJ3Mge2lkZW50aXR5LWNvbnN0cmFpbnQgZGVmaW5pdGlvbnN9IGlzIGEgc3Vic2V0IG9mIEIncyBkZWNsYXJhdGlvbidzIHtpZGVudGl0eS1jb25zdHJhaW50IGRlZmluaXRpb25zfSwgaWYgYW55LgogICAgICAgIGJvb2xlYW4gaWRlbnRpdHlDb25zdHJhaW50c09LID0gdHJ1ZTsKCiAgICAgICAgU2NoZW1hSWRlbnRpdHlDb25zdHJhaW50W10gYmFzZUNvbnN0cmFpbnRzID0gYmFzZUVsZW1lbnQuZ2V0SWRlbnRpdHlDb25zdHJhaW50cygpOwogICAgICAgIFNjaGVtYUlkZW50aXR5Q29uc3RyYWludFtdIGRlcml2ZWRDb25zdHJhaW50cyA9IGRlcml2ZWRFbGVtZW50LmdldElkZW50aXR5Q29uc3RyYWludHMoKTsKICAgICAgICAvLyBjeWNsZSB0aHJ1IGRlcml2ZWQncyBpZGVudGl0eSBjb25zdHJhaW50cyBhbmQgY2hlY2sgZWFjaCB0byBhc3N1cmUgdGhleSBpbiB0aGUgYXJyYXkgb2YgYmFzZSBjb25zdHJhaW50cwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgZGVyaXZlZENvbnN0cmFpbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIFNjaGVtYUlkZW50aXR5Q29uc3RyYWludCBkZXJpdmVkQ29uc3RyYWludCA9IGRlcml2ZWRDb25zdHJhaW50c1tpXTsKICAgICAgICAgICAgaWYgKGNoZWNrRm9ySWRlbnRpdHlDb25zdHJhaW50RXhpc3RlbmNlKGJhc2VDb25zdHJhaW50cywgZGVyaXZlZENvbnN0cmFpbnQpKSB7CiAgICAgICAgICAgICAgICBpZGVudGl0eUNvbnN0cmFpbnRzT0sgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdElkZW50aXR5Q29uc3RyYWludHNOb3RTdWJzZXRFcnJvcihiYXNlRWxlbWVudCwgZGVyaXZlZEVsZW1lbnQpLCBjb250ZXh0KSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaWRlbnRpdHlDb25zdHJhaW50c09LOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXRJZGVudGl0eUNvbnN0cmFpbnRzTm90U3Vic2V0RXJyb3IoU2NoZW1hTG9jYWxFbGVtZW50IGJhc2VFbGVtZW50LCBTY2hlbWFMb2NhbEVsZW1lbnQgZGVyaXZlZEVsZW1lbnQpIHsKICAgICAgICByZXR1cm4gIlJlc3RyaWN0aW9uIEludmFsaWQuICBUaGUgaWRlbnRpdHkgY29uc3RyYWludHMgZm9yICIgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSlkZXJpdmVkRWxlbWVudCkKICAgICAgICAgICAgICAgICsgIiBhcmUgbm90IGEgc3Vic2V0IG9mIHRoZSBpZGVudGl0eSBjb25zdHJhaW50cyBmb3IgIiArIHByaW50UGFydGljbGUoKFNjaGVtYVBhcnRpY2xlKWJhc2VFbGVtZW50KTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBib29sZWFuIGNoZWNrRm9ySWRlbnRpdHlDb25zdHJhaW50RXhpc3RlbmNlKFNjaGVtYUlkZW50aXR5Q29uc3RyYWludFtdIGJhc2VDb25zdHJhaW50cywgU2NoZW1hSWRlbnRpdHlDb25zdHJhaW50IGRlcml2ZWRDb25zdHJhaW50KSB7CiAgICAgICAgLy8gc3BpbiB0aHJ1IHRoZSBiYXNlIGlkZW50aXR5IGNvbnN0cmFpbnRzIGNoZWNrIHRvIHNlZSBpZiBkZXJpdmVkIGNvbnN0cmFpbnQgZXhpc3RzCiAgICAgICAgYm9vbGVhbiBpZGVudGl0eUNvbnN0cmFpbnRFeGlzdHMgPSBmYWxzZTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGJhc2VDb25zdHJhaW50cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBTY2hlbWFJZGVudGl0eUNvbnN0cmFpbnQgYmFzZUNvbnN0cmFpbnQgPSBiYXNlQ29uc3RyYWludHNbaV07CiAgICAgICAgICAgIGlmIChiYXNlQ29uc3RyYWludC5nZXROYW1lKCkuZXF1YWxzKGRlcml2ZWRDb25zdHJhaW50LmdldE5hbWUoKSkpIHsKICAgICAgICAgICAgICAgIGlkZW50aXR5Q29uc3RyYWludEV4aXN0cyA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaWRlbnRpdHlDb25zdHJhaW50RXhpc3RzOwogICAgfQoKCiAgICBwcml2YXRlIHN0YXRpYyBib29sZWFuIGNoZWNrRml4ZWQoU2NoZW1hTG9jYWxFbGVtZW50IGJhc2VNb2RlbCwgU2NoZW1hTG9jYWxFbGVtZW50IGRlcml2ZWRNb2RlbCwgQ29sbGVjdGlvbiBlcnJvcnMsIFhtbE9iamVjdCBjb250ZXh0KSB7CiAgICAgICAgLy8gNCBlaXRoZXIgQidzIGRlY2xhcmF0aW9uJ3Mge3ZhbHVlIGNvbnN0cmFpbnR9IGlzIGFic2VudCwgb3IgaXMgbm90IGZpeGVkLAogICAgICAgIC8vIG9yIFIncyBkZWNsYXJhdGlvbidzIHt2YWx1ZSBjb25zdHJhaW50fSBpcyBmaXhlZCB3aXRoIHRoZSBzYW1lIHZhbHVlLgogICAgICAgIGJvb2xlYW4gY2hlY2tGaXhlZCA9IGZhbHNlOwogICAgICAgIGlmIChiYXNlTW9kZWwuaXNGaXhlZCgpKSB7CiAgICAgICAgICAgIGlmIChiYXNlTW9kZWwuZ2V0RGVmYXVsdFRleHQoKS5lcXVhbHMoZGVyaXZlZE1vZGVsLmdldERlZmF1bHRUZXh0KCkpKSB7CiAgICAgICAgICAgICAgICAvLyAgUidzIGRlY2xhcmF0aW9uJ3Mge3ZhbHVlIGNvbnN0cmFpbnR9IGlzIGZpeGVkIHdpdGggdGhlIHNhbWUgdmFsdWUuCiAgICAgICAgICAgICAgICBjaGVja0ZpeGVkID0gdHJ1ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIFRoZSBkZXJpdmVkIGVsZW1lbnQgaGFzIGEgZml4ZWQgdmFsdWUgdGhhdCBpcyBkaWZmZXJlbnQgdGhhbiB0aGUgYmFzZSBlbGVtZW50CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRJbnZhbGlkRml4ZWRFcnJvcihiYXNlTW9kZWwsIGRlcml2ZWRNb2RlbCksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgIGNoZWNrRml4ZWQgPSBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vICBCJ3MgZGVjbGFyYXRpb24ncyB7dmFsdWUgY29uc3RyYWludH0gaXMgYWJzZW50LCBvciBpcyBub3QgZml4ZWQsCiAgICAgICAgICAgIGNoZWNrRml4ZWQgPSB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY2hlY2tGaXhlZDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0SW52YWxpZEZpeGVkRXJyb3IoU2NoZW1hTG9jYWxFbGVtZW50IGJhc2VNb2RlbCwgU2NoZW1hTG9jYWxFbGVtZW50IGRlcml2ZWRNb2RlbCkgewogICAgICAgIHJldHVybiAiVGhlIERlcml2ZWQgQ29udGVudCBNb2RlbCBvbiBFbGVtZW50OiAnIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSlkZXJpdmVkTW9kZWwpCiAgICAgICAgICAgICAgICArICInIGhhcyBhIGZpeGVkIHZhbHVlIG9mOiAnIgogICAgICAgICAgICAgICAgKyBkZXJpdmVkTW9kZWwuZ2V0RGVmYXVsdFRleHQoKQogICAgICAgICAgICAgICAgKyAiJyB3aGljaCBkb2VzIG5vdCBtYXRjaCB0aGUgQmFzZSBDb250ZW50IE1vZGVsOiAnIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKChTY2hlbWFQYXJ0aWNsZSliYXNlTW9kZWwpCiAgICAgICAgICAgICAgICArICInIHdoYXQgaGFzIGEgZml4ZWQgdmFsdWUgb2Y6ICciCiAgICAgICAgICAgICAgICArIGJhc2VNb2RlbC5nZXREZWZhdWx0VGV4dCgpICsgIiciOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gb2NjdXJyZW5jZVJhbmdlT0soU2NoZW1hUGFydGljbGUgYmFzZVBhcnRpY2xlLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkUGFydGljbGUsIENvbGxlY3Rpb24gZXJyb3JzLCBYbWxPYmplY3QgY29udGV4dCkgewogICAgICAgIGJvb2xlYW4gb2NjdXJyZW5jZVJhbmdlT0sgPSBmYWxzZTsKICAgICAgICAvLyBOb3RlOiBpbiB0aGUgZm9sbG93aW5nIGNvbW1lbnRzIChmcm9tIHRoZSBzY2hlbWEgc3BlYykgb3RoZXIgaXMgdGhlIGJhc2VNb2RlbAogICAgICAgIC8vIDEgSXRzIHttaW4gb2NjdXJzfSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIG90aGVyJ3Mge21pbiBvY2N1cnN9LgogICAgICAgIGlmIChkZXJpdmVkUGFydGljbGUuZ2V0TWluT2NjdXJzKCkuY29tcGFyZVRvKGJhc2VQYXJ0aWNsZS5nZXRNaW5PY2N1cnMoKSkgPj0gMCkgewogICAgICAgICAgICAvLyAyIG9uZSBvZiB0aGUgZm9sbG93aW5nIG11c3QgYmUgdHJ1ZToKICAgICAgICAgICAgLy8gMi4xIFRoZSBvdGhlcidzIHttYXggb2NjdXJzfSBpcyB1bmJvdW5kZWQuCiAgICAgICAgICAgIGlmIChiYXNlUGFydGljbGUuZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgb2NjdXJyZW5jZVJhbmdlT0sgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gMi4yIEJvdGgge21heCBvY2N1cnN9IGFyZSBudW1iZXJzLCBhbmQgdGhlIHBhcnRpY2xlJ3MgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvdGhlcidzLgogICAgICAgICAgICAgICAgaWYgKGRlcml2ZWRQYXJ0aWNsZS5nZXRNYXhPY2N1cnMoKSAhPSBudWxsICYmIGJhc2VQYXJ0aWNsZS5nZXRNYXhPY2N1cnMoKSAhPSBudWxsICYmCiAgICAgICAgICAgICAgICAgICAgICAgIGRlcml2ZWRQYXJ0aWNsZS5nZXRNYXhPY2N1cnMoKS5jb21wYXJlVG8oYmFzZVBhcnRpY2xlLmdldE1heE9jY3VycygpKSA8PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgb2NjdXJyZW5jZVJhbmdlT0sgPSB0cnVlOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBvY2N1cnJlbmNlUmFuZ2VPSyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmIChiYXNlUGFydGljbGUuZ2V0TmFtZSgpID09IG51bGwgfHwgZGVyaXZlZFBhcnRpY2xlLmdldE5hbWUoKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycy5hZGQoWG1sRXJyb3IuZm9yT2JqZWN0KGZvcm1hdE9jY3VyZW5jZVJhbmdlTWF4RXJyb3JHcm91cChiYXNlUGFydGljbGUsIGRlcml2ZWRQYXJ0aWNsZSksIGNvbnRleHQpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRPY2N1cmVuY2VSYW5nZU1heEVycm9yKGJhc2VQYXJ0aWNsZSwgZGVyaXZlZFBhcnRpY2xlKSwgY29udGV4dCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9jY3VycmVuY2VSYW5nZU9LID0gZmFsc2U7CiAgICAgICAgICAgIGlmIChiYXNlUGFydGljbGUuZ2V0TmFtZSgpID09IG51bGwgfHwgZGVyaXZlZFBhcnRpY2xlLmdldE5hbWUoKSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRPY2N1cmVuY2VSYW5nZU1pbkVycm9yR3JvdXAoYmFzZVBhcnRpY2xlLCBkZXJpdmVkUGFydGljbGUpLCBjb250ZXh0KSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBlcnJvcnMuYWRkKFhtbEVycm9yLmZvck9iamVjdChmb3JtYXRPY2N1cmVuY2VSYW5nZU1pbkVycm9yKGJhc2VQYXJ0aWNsZSwgZGVyaXZlZFBhcnRpY2xlKSwgY29udGV4dCkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBvY2N1cnJlbmNlUmFuZ2VPSzsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0T2NjdXJlbmNlUmFuZ2VNYXhFcnJvckdyb3VwKFNjaGVtYVBhcnRpY2xlIGJhc2VQYXJ0aWNsZSwgU2NoZW1hUGFydGljbGUgZGVyaXZlZFBhcnRpY2xlKSB7CiAgICAgICAgcmV0dXJuICJJbnZhbGlkIFJlc3RyaWN0aW9uLiAgVGhlIG1heE9jY3VycyBmb3IgdGhlICIKICAgICAgICAgICAgICAgICsgcHJpbnRQYXJ0aWNsZShkZXJpdmVkUGFydGljbGUpCiAgICAgICAgICAgICAgICArICIgKCIgKyBwcmludE1heE9jY3VycyhkZXJpdmVkUGFydGljbGUuZ2V0TWF4T2NjdXJzKCkpCiAgICAgICAgICAgICAgICArICIpIGlzIGdyZWF0ZXIgdGhhbiB0aGFuIHRoZSBtYXhPY2N1cnMgZm9yIHRoZSBiYXNlICIKICAgICAgICAgICAgICAgICsgcHJpbnRQYXJ0aWNsZShiYXNlUGFydGljbGUpCiAgICAgICAgICAgICAgICArICIgKCIgKyBwcmludE1heE9jY3VycyhiYXNlUGFydGljbGUuZ2V0TWF4T2NjdXJzKCkpICsgIikiOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBmb3JtYXRPY2N1cmVuY2VSYW5nZU1pbkVycm9yR3JvdXAoU2NoZW1hUGFydGljbGUgYmFzZVBhcnRpY2xlLCBTY2hlbWFQYXJ0aWNsZSBkZXJpdmVkUGFydGljbGUpIHsKICAgICAgICByZXR1cm4gIkludmFsaWQgUmVzdHJpY3Rpb24uICBUaGUgbWluT2NjdXJzIGZvciB0aGUgIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRQYXJ0aWNsZSkKICAgICAgICAgICAgICAgICsgIiAoIiArIGRlcml2ZWRQYXJ0aWNsZS5nZXRNaW5PY2N1cnMoKS50b1N0cmluZygpCiAgICAgICAgICAgICAgICArICIpIGlzIGxlc3MgdGhhbiB0aGFuIHRoZSBtaW5PY2N1cnMgZm9yIHRoZSBiYXNlICIKICAgICAgICAgICAgICAgICsgcHJpbnRQYXJ0aWNsZShiYXNlUGFydGljbGUpCiAgICAgICAgICAgICAgICArICIgKCIgKyBiYXNlUGFydGljbGUuZ2V0TWluT2NjdXJzKCkudG9TdHJpbmcoKSArICIpIjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0T2NjdXJlbmNlUmFuZ2VNaW5FcnJvcihTY2hlbWFQYXJ0aWNsZSBiYXNlRmllbGQsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRGaWVsZCkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIFRoZSBtaW5PY2N1cnMgZm9yIHRoZSBlbGVtZW50OiAnIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRGaWVsZCkKICAgICAgICAgICAgICAgICsgIicgKCIgKyBkZXJpdmVkRmllbGQuZ2V0TWluT2NjdXJzKCkudG9TdHJpbmcoKQogICAgICAgICAgICAgICAgKyAiKSBpcyBsZXNzIHRoYW4gdGhhbiB0aGUgbWluT2NjdXJzIGZvciB0aGUgYmFzZSBlbGVtZW50OiAnIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGJhc2VGaWVsZCkKICAgICAgICAgICAgICAgICsgIicgKCIgKyBiYXNlRmllbGQuZ2V0TWluT2NjdXJzKCkudG9TdHJpbmcoKSArICIpIjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZm9ybWF0T2NjdXJlbmNlUmFuZ2VNYXhFcnJvcihTY2hlbWFQYXJ0aWNsZSBiYXNlRmllbGQsIFNjaGVtYVBhcnRpY2xlIGRlcml2ZWRGaWVsZCkgewogICAgICAgIHJldHVybiAiSW52YWxpZCBSZXN0cmljdGlvbi4gIFRoZSBtYXhPY2N1cnMgZm9yIHRoZSBlbGVtZW50OiAnIgogICAgICAgICAgICAgICAgKyBwcmludFBhcnRpY2xlKGRlcml2ZWRGaWVsZCkKICAgICAgICAgICAgICAgICsgIicgKCIgKyBwcmludE1heE9jY3VycyhkZXJpdmVkRmllbGQuZ2V0TWF4T2NjdXJzKCkpCiAgICAgICAgICAgICAgICArICIpIGlzIGdyZWF0ZXIgdGhhbiB0aGFuIHRoZSBtYXhPY2N1cnMgZm9yIHRoZSBiYXNlIGVsZW1lbnQ6ICciCiAgICAgICAgICAgICAgICArIHByaW50UGFydGljbGUoYmFzZUZpZWxkKSArICInICgiICsgcHJpbnRNYXhPY2N1cnMoYmFzZUZpZWxkLmdldE1heE9jY3VycygpKSArICIpIjsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIHByaW50UGFydGljbGUoU2NoZW1hUGFydGljbGUgcGFydCkKICAgIHsKICAgICAgICBzd2l0Y2ggKHBhcnQuZ2V0UGFydGljbGVUeXBlKCkpIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICByZXR1cm4gIjxhbGw+IjsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICByZXR1cm4gIjxjaG9pY2U+IjsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgcmV0dXJuICI8ZWxlbWVudCBuYW1lPVwiIiArIFFOYW1lSGVscGVyLnByZXR0eShwYXJ0LmdldE5hbWUoKSkgKyAiXCI+IjsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgICAgIHJldHVybiAiPHNlcXVlbmNlPiI7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICByZXR1cm4gIjxhbnk+IjsKICAgICAgICAgICAgZGVmYXVsdCA6CiAgICAgICAgICAgICAgICByZXR1cm4gIj8/IjsKICAgICAgICB9CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBwcmludE1heE9jY3VycyhCaWdJbnRlZ2VyIGJpKQogICAgewogICAgICAgIGlmIChiaSA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gInVuYm91bmRlZCI7CiAgICAgICAgcmV0dXJuIGJpLnRvU3RyaW5nKCk7CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBwcmludFR5cGUoU2NoZW1hVHlwZSB0eXBlKQogICAgewogICAgICAgIGlmICh0eXBlLmdldE5hbWUoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gUU5hbWVIZWxwZXIucHJldHR5KHR5cGUuZ2V0TmFtZSgpKTsKICAgICAgICByZXR1cm4gdHlwZS50b1N0cmluZygpOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgY2hlY2tTdWJzdGl0dXRpb25Hcm91cHMoU2NoZW1hR2xvYmFsRWxlbWVudFtdIGVsdHMpCiAgICB7CiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwoKICAgICAgICBmb3IgKGludCBpID0gMCA7IGkgPCBlbHRzLmxlbmd0aCA7IGkrKykKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYUdsb2JhbEVsZW1lbnQgZWx0ID0gZWx0c1tpXTsKICAgICAgICAgICAgU2NoZW1hR2xvYmFsRWxlbWVudCBoZWFkID0gZWx0LnN1YnN0aXR1dGlvbkdyb3VwKCk7CgogICAgICAgICAgICBpZiAoaGVhZCAhPSBudWxsKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBTY2hlbWFUeXBlIGhlYWRUeXBlID0gaGVhZC5nZXRUeXBlKCk7CiAgICAgICAgICAgICAgICBTY2hlbWFUeXBlIHRhaWxUeXBlID0gZWx0LmdldFR5cGUoKTsKICAgICAgICAgICAgICAgIFhtbE9iamVjdCBwYXJzZVRyZWUgPSAoKFNjaGVtYUdsb2JhbEVsZW1lbnRJbXBsKWVsdCkuX3BhcnNlT2JqZWN0OwoKICAgICAgICAgICAgICAgIGlmICghIGhlYWRUeXBlLmlzQXNzaWduYWJsZUZyb20odGFpbFR5cGUpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJFbGVtZW50ICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoZWx0LmdldE5hbWUoKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAiIG11c3QgaGF2ZSBhIHR5cGUgdGhhdCBpcyBkZXJpdmVkIGZyb20gdGhlIHR5cGUgb2YgaXRzIHN1YnN0aXR1dGlvbiBncm91cC4iLAogICAgICAgICAgICAgICAgICAgICAgICBYbWxFcnJvckNvbnRleHQuSU5DT05TSVNURU5UX1RZUEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIGlmIChoZWFkLmZpbmFsRXh0ZW5zaW9uKCkgJiYgaGVhZC5maW5hbFJlc3RyaWN0aW9uKCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkVsZW1lbnQgIiArIFFOYW1lSGVscGVyLnByZXR0eShlbHQuZ2V0TmFtZSgpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAiIGNhbm5vdCBiZSBzdWJzdGl0dXRlZCBmb3IgZWxlbWVudCB3aXRoIGZpbmFsPScjYWxsJyIsCiAgICAgICAgICAgICAgICAgICAgICAgIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSBpZiAoISBoZWFkVHlwZS5lcXVhbHModGFpbFR5cGUpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChoZWFkLmZpbmFsRXh0ZW5zaW9uKCkgJiYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFpbFR5cGUuZ2V0RGVyaXZhdGlvblR5cGUoKSA9PSBTY2hlbWFUeXBlLkRUX0VYVEVOU0lPTikKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJFbGVtZW50ICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoZWx0LmdldE5hbWUoKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICIgY2Fubm90IGJlIHN1YnN0aXR1dGVkIGZvciBlbGVtZW50IHdpdGggZmluYWw9J2V4dGVuc2lvbiciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWG1sRXJyb3JDb250ZXh0LkNBTk5PVF9ERVJJVkVfRklOQUwsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGhlYWQuZmluYWxSZXN0cmljdGlvbigpICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFpbFR5cGUuZ2V0RGVyaXZhdGlvblR5cGUoKSA9PSBTY2hlbWFUeXBlLkRUX1JFU1RSSUNUSU9OKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkVsZW1lbnQgIiArIFFOYW1lSGVscGVyLnByZXR0eShlbHQuZ2V0TmFtZSgpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIiBjYW5ub3QgYmUgc3Vic3RpdHV0ZWQgZm9yIGVsZW1lbnQgd2l0aCBmaW5hbD0ncmVzdHJpY3Rpb24nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICB9CiAgICB9Cn0K