LyogICBDb3B5cmlnaHQgMjAwNCBUaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24KICoKICogICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogICB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiAqICAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiAgIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiAgIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiAgIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKi8KCnBhY2thZ2Ugb3JnLmFwYWNoZS54bWxiZWFucy5pbXBsLnNjaGVtYTsKCmltcG9ydCBqYXZhLm1hdGguQmlnSW50ZWdlcjsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CgppbXBvcnQgb3JnLnczLngyMDAxLnhtbFNjaGVtYS4qOwppbXBvcnQgb3JnLnczLngyMDAxLnhtbFNjaGVtYS5TY2hlbWFEb2N1bWVudC5TY2hlbWE7CmltcG9ydCBvcmcudzMueDIwMDEueG1sU2NoZW1hLkFueURvY3VtZW50LkFueTsKaW1wb3J0IGphdmF4LnhtbC5uYW1lc3BhY2UuUU5hbWU7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLmltcGwuY29tbW9uLlhtbEVycm9yQ29udGV4dDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuaW1wbC5jb21tb24uUU5hbWVIZWxwZXI7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlhtbE9iamVjdDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuUU5hbWVTZXRCdWlsZGVyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5YbWxJbnRlZ2VyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFGaWVsZDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hVHlwZTsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hUGFydGljbGU7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlhtbEN1cnNvcjsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hQXR0cmlidXRlTW9kZWw7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYVByb3BlcnR5OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5RTmFtZVNldDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuWG1sTm9uTmVnYXRpdmVJbnRlZ2VyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFMb2NhbEF0dHJpYnV0ZTsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hTG9jYWxFbGVtZW50OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5RTmFtZVNldFNwZWNpZmljYXRpb247CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlhtbEJlYW5zOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5pbXBsLmNvbW1vbi5TZXF1ZW5jZWRIYXNoTWFwOwoKcHVibGljIGNsYXNzIFN0c2NDb21wbGV4VHlwZVJlc29sdmVyCnsKICAgIHB1YmxpYyBzdGF0aWMgR3JvdXAgZ2V0Q29udGVudE1vZGVsKENvbXBsZXhUeXBlIHBhcnNlQ3QpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlQ3QuZ2V0QWxsKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlQ3QuZ2V0QWxsKCk7CgogICAgICAgIGlmIChwYXJzZUN0LmdldFNlcXVlbmNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlQ3QuZ2V0U2VxdWVuY2UoKTsKCiAgICAgICAgaWYgKHBhcnNlQ3QuZ2V0Q2hvaWNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlQ3QuZ2V0Q2hvaWNlKCk7CgogICAgICAgIGlmIChwYXJzZUN0LmdldEdyb3VwKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlQ3QuZ2V0R3JvdXAoKTsKCiAgICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBHcm91cCBnZXRDb250ZW50TW9kZWwoQ29tcGxleFJlc3RyaWN0aW9uVHlwZSBwYXJzZVJlc3QpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlUmVzdC5nZXRBbGwoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VSZXN0LmdldEFsbCgpOwoKICAgICAgICBpZiAocGFyc2VSZXN0LmdldFNlcXVlbmNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlUmVzdC5nZXRTZXF1ZW5jZSgpOwoKICAgICAgICBpZiAocGFyc2VSZXN0LmdldENob2ljZSgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZVJlc3QuZ2V0Q2hvaWNlKCk7CgogICAgICAgIGlmIChwYXJzZVJlc3QuZ2V0R3JvdXAoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VSZXN0LmdldEdyb3VwKCk7CgogICAgICAgIHJldHVybiBudWxsOwoKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIEdyb3VwIGdldENvbnRlbnRNb2RlbChFeHRlbnNpb25UeXBlIHBhcnNlRXh0KQogICAgewogICAgICAgIGlmIChwYXJzZUV4dC5nZXRBbGwoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VFeHQuZ2V0QWxsKCk7CgogICAgICAgIGlmIChwYXJzZUV4dC5nZXRTZXF1ZW5jZSgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZUV4dC5nZXRTZXF1ZW5jZSgpOwoKICAgICAgICBpZiAocGFyc2VFeHQuZ2V0Q2hvaWNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlRXh0LmdldENob2ljZSgpOwoKICAgICAgICBpZiAocGFyc2VFeHQuZ2V0R3JvdXAoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VFeHQuZ2V0R3JvdXAoKTsKCiAgICAgICAgcmV0dXJuIG51bGw7CgogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFNjaGVtYSBnZXRTY2hlbWEoWG1sT2JqZWN0IG8pCiAgICB7CiAgICAgICAgWG1sQ3Vyc29yIGMgPSBvLm5ld0N1cnNvcigpOwogICAgICAgIAogICAgICAgIHRyeQogICAgICAgIHsKICAgICAgICAgICAgd2hpbGUgKCBjLnRvUGFyZW50KCkgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBvID0gYy5nZXRPYmplY3QoKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgKG8uc2NoZW1hVHlwZSgpLmVxdWFscyhTY2hlbWEudHlwZSkpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChTY2hlbWEpIG87CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZmluYWxseQogICAgICAgIHsKICAgICAgICAgICAgYy5kaXNwb3NlKCk7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCByZXNvbHZlQ29tcGxleFR5cGUoU2NoZW1hVHlwZUltcGwgc0ltcGwpCiAgICB7CiAgICAgICAgQ29tcGxleFR5cGUgcGFyc2VDdCA9IChDb21wbGV4VHlwZSlzSW1wbC5nZXRQYXJzZU9iamVjdCgpOwogICAgICAgIFN0c2NTdGF0ZSBzdGF0ZSA9IFN0c2NTdGF0ZS5nZXQoKTsKICAgICAgICBTY2hlbWEgc2NoZW1hID0gZ2V0U2NoZW1hKHBhcnNlQ3QpOwoKICAgICAgICAvLyBTZXQgYWJzdHJhY3QgJiBmaW5hbCBmbGFncwogICAgICAgIGJvb2xlYW4gYWJzID0gcGFyc2VDdC5pc1NldEFic3RyYWN0KCkgPyBwYXJzZUN0LmdldEFic3RyYWN0KCkgOiBmYWxzZTsKICAgICAgICBib29sZWFuIGZpbmFsRXh0ID0gZmFsc2U7CiAgICAgICAgYm9vbGVhbiBmaW5hbFJlc3QgPSBmYWxzZTsKICAgICAgICBib29sZWFuIGZpbmFsTGlzdCA9IGZhbHNlOwogICAgICAgIGJvb2xlYW4gZmluYWxVbmlvbiA9IGZhbHNlOwoKICAgICAgICBPYmplY3QgZHMgPSBudWxsOwogICAgICAgIGlmIChwYXJzZUN0LmlzU2V0RmluYWwoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRzID0gcGFyc2VDdC5nZXRGaW5hbCgpOwogICAgICAgIH0KICAgICAgICAvLyBJbnNwZWN0IHRoZSBmaW5hbCBkZWZhdWx0IGF0dHJpYnV0ZSBvbiB0aGUgc2NoZW1hCiAgICAgICAgZWxzZSBpZiAoc2NoZW1hICE9IG51bGwgJiYgc2NoZW1hLmlzU2V0RmluYWxEZWZhdWx0KCkpCiAgICAgICAgewogICAgICAgICAgICBkcyA9IHNjaGVtYS5nZXRGaW5hbERlZmF1bHQoKTsKICAgICAgICB9CgogICAgICAgIGlmIChkcyAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGRzIGluc3RhbmNlb2YgU3RyaW5nICYmIGRzLmVxdWFscygiI2FsbCIpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyAjQUxMIHZhbHVlCiAgICAgICAgICAgICAgICBmaW5hbEV4dCA9IGZpbmFsUmVzdCA9IGZpbmFsTGlzdCA9IGZpbmFsVW5pb24gPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGRzIGluc3RhbmNlb2YgTGlzdCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKCgoTGlzdClkcykuY29udGFpbnMoImV4dGVuc2lvbiIpKQogICAgICAgICAgICAgICAgICAgIGZpbmFsRXh0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgKCgoTGlzdClkcykuY29udGFpbnMoInJlc3RyaWN0aW9uIikpCiAgICAgICAgICAgICAgICAgICAgZmluYWxSZXN0ID0gdHJ1ZTsKCi8vIFNpbmNlIGNvbXBsZXggdHlwZXMgZG9uJ3QgcGFydGljaXBhdGUgaW4gbGlzdCBhbmQgdW5pb25zLCB0aGVzZSBjYW4gcmVtYWluCi8vIGZhbHNlLiAgUGVyaGFwcyB3ZSBzaG91bGQgdGhyb3cgYW4gZXJyb3IuCgovLyAgICAgICAgICAgICAgICBpZiAoKChMaXN0KWRzKS5jb250YWlucygibGlzdCIpKQovLyAgICAgICAgICAgICAgICAgICAgZmluYWxMaXN0ID0gdHJ1ZTsKLy8gICAgICAgICAgICAgICAgCi8vICAgICAgICAgICAgICAgIGlmICgoKExpc3QpZHMpLmNvbnRhaW5zKCJ1bmlvbiIpKQovLyAgICAgICAgICAgICAgICAgICAgZmluYWxVbmlvbiA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHNJbXBsLnNldEFic3RyYWN0RmluYWwoYWJzLCBmaW5hbEV4dCwgZmluYWxSZXN0LCBmaW5hbExpc3QsIGZpbmFsVW5pb24pOwoKICAgICAgICAvLyBTZXQgYmxvY2sgZmxhZ3MKICAgICAgICBib29sZWFuIGJsb2NrRXh0ID0gZmFsc2U7CiAgICAgICAgYm9vbGVhbiBibG9ja1Jlc3QgPSBmYWxzZTsKICAgICAgICBPYmplY3QgYmxvY2sgPSBudWxsOwoKICAgICAgICBpZiAocGFyc2VDdC5pc1NldEJsb2NrKCkpCiAgICAgICAgICAgIGJsb2NrID0gcGFyc2VDdC5nZXRCbG9jaygpOwogICAgICAgIGVsc2UgaWYgKHNjaGVtYSAhPSBudWxsICYmIHNjaGVtYS5pc1NldEJsb2NrRGVmYXVsdCgpKQogICAgICAgICAgICBibG9jayA9IHNjaGVtYS5nZXRCbG9ja0RlZmF1bHQoKTsKCiAgICAgICAgaWYgKGJsb2NrICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBpZiAoYmxvY2sgaW5zdGFuY2VvZiBTdHJpbmcgJiYgYmxvY2suZXF1YWxzKCIjYWxsIikpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vICNBTEwgdmFsdWUKICAgICAgICAgICAgICAgIGJsb2NrRXh0ID0gYmxvY2tSZXN0ID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChibG9jayBpbnN0YW5jZW9mIExpc3QpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmICgoKExpc3QpYmxvY2spLmNvbnRhaW5zKCJleHRlbnNpb24iKSkKICAgICAgICAgICAgICAgICAgICBibG9ja0V4dCA9IHRydWU7CiAgICAgICAgICAgICAgICBpZiAoKChMaXN0KWJsb2NrKS5jb250YWlucygicmVzdHJpY3Rpb24iKSkKICAgICAgICAgICAgICAgICAgICBibG9ja1Jlc3QgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzSW1wbC5zZXRCbG9jayhibG9ja0V4dCwgYmxvY2tSZXN0KTsKCiAgICAgICAgLy8gVmVyaWZ5OiBoYXZlIHNpbXBsZUNvbnRlbnQsIGNvbXBsZXhDb250ZW50LCBvciBkaXJlY3Qgc3R1ZmYKICAgICAgICBDb21wbGV4Q29udGVudERvY3VtZW50LkNvbXBsZXhDb250ZW50IHBhcnNlQ2MgPSBwYXJzZUN0LmdldENvbXBsZXhDb250ZW50KCk7CiAgICAgICAgU2ltcGxlQ29udGVudERvY3VtZW50LlNpbXBsZUNvbnRlbnQgcGFyc2VTYyA9IHBhcnNlQ3QuZ2V0U2ltcGxlQ29udGVudCgpOwogICAgICAgIEdyb3VwIHBhcnNlR3JvdXAgPSBnZXRDb250ZW50TW9kZWwocGFyc2VDdCk7CiAgICAgICAgaW50IGNvdW50ID0KICAgICAgICAgICAgICAgIChwYXJzZUNjICE9IG51bGwgPyAxIDogMCkgKwogICAgICAgICAgICAgICAgKHBhcnNlU2MgIT0gbnVsbCA/IDEgOiAwKSArCiAgICAgICAgICAgICAgICAocGFyc2VHcm91cCAhPSBudWxsID8gMSA6IDApOwogICAgICAgIGlmIChjb3VudCA+IDEpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSBjb21wbGV4IHR5cGUgbXVzdCBkZWZpbmUgZWl0aGVyIGEgY29udGVudCBtb2RlbCwgIiArCiAgICAgICAgICAgICAgICAgICAgICAib3IgYSBzaW1wbGVDb250ZW50IG9yIGNvbXBsZXhDb250ZW50IGRlcml2YXRpb246ICIgKwogICAgICAgICAgICAgICAgICAgICAgIm1vcmUgdGhhbiBvbmUgZm91bmQuIiwKICAgICAgICAgICAgICAgICAgICBYbWxFcnJvckNvbnRleHQuUkVEVU5EQU5UX0NPTlRFTlRfTU9ERUwsIHBhcnNlQ3QpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogdHJlYXQgaXQgYXMgdGhlIGZpcnN0IG9mIGNvbXBsZXhDb250ZW50LCBzaW1wbGVDb250ZW50LCBtb2RlbAogICAgICAgICAgICBwYXJzZUdyb3VwID0gbnVsbDsKICAgICAgICAgICAgaWYgKHBhcnNlQ2MgIT0gbnVsbCAmJiBwYXJzZVNjICE9IG51bGwpCiAgICAgICAgICAgICAgICBwYXJzZVNjID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYgKHBhcnNlQ2MgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChwYXJzZUNjLmdldEV4dGVuc2lvbigpICE9IG51bGwgJiYgcGFyc2VDYy5nZXRSZXN0cmljdGlvbigpICE9IG51bGwpCiAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiUmVzdHJpY3Rpb24gY29uZmxpY3RzIHdpdGggZXh0ZW5zaW9uIiwgWG1sRXJyb3JDb250ZXh0LlJFRFVOREFOVF9DT05URU5UX01PREVMLCBwYXJzZUNjLmdldFJlc3RyaWN0aW9uKCkpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gTWl4ZWQgY2FuIGJlIHNwZWNpZmllZCBpbiB0d28gcGxhY2VzOiB0aGUgcnVsZXMgYXJlIHRoYXQgQ2Mgd2lucyBvdmVyIEN0IGlmIHByZXNlbnQKICAgICAgICAgICAgLy8gaHR0cDovL3d3dy53My5vcmcvVFIveG1sc2NoZW1hLTEvI2MtbXZlCiAgICAgICAgICAgIGJvb2xlYW4gbWl4ZWQgPSBwYXJzZUNjLmlzU2V0TWl4ZWQoKSA/IHBhcnNlQ2MuZ2V0TWl4ZWQoKSA6IHBhcnNlQ3QuZ2V0TWl4ZWQoKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIChwYXJzZUNjLmdldEV4dGVuc2lvbigpICE9IG51bGwpCiAgICAgICAgICAgICAgICByZXNvbHZlQ2NFeHRlbnNpb24oc0ltcGwsIHBhcnNlQ2MuZ2V0RXh0ZW5zaW9uKCksIG1peGVkKTsKICAgICAgICAgICAgZWxzZSBpZiAocGFyc2VDYy5nZXRSZXN0cmljdGlvbigpICE9IG51bGwpCiAgICAgICAgICAgICAgICByZXNvbHZlQ2NSZXN0cmljdGlvbihzSW1wbCwgcGFyc2VDYy5nZXRSZXN0cmljdGlvbigpLCBtaXhlZCk7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk1pc3NpbmcgcmVzdHJpY3Rpb24gb3IgZXh0ZW5zaW9uIiwgWG1sRXJyb3JDb250ZXh0Lk1JU1NJTkdfUkVTVFJJQ1RJT05fT1JfRVhURU5TSU9OLCBwYXJzZUNjKTsKICAgICAgICAgICAgICAgIHJlc29sdmVFcnJvclR5cGUoc0ltcGwpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAocGFyc2VTYyAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHBhcnNlU2MuZ2V0RXh0ZW5zaW9uKCkgIT0gbnVsbCAmJiBwYXJzZVNjLmdldFJlc3RyaWN0aW9uKCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJSZXN0cmljdGlvbiBjb25mbGljdHMgd2l0aCBleHRlbnNpb24iLCBYbWxFcnJvckNvbnRleHQuUkVEVU5EQU5UX0NPTlRFTlRfTU9ERUwsIHBhcnNlU2MuZ2V0UmVzdHJpY3Rpb24oKSk7CgogICAgICAgICAgICBpZiAocGFyc2VTYy5nZXRFeHRlbnNpb24oKSAhPSBudWxsKQogICAgICAgICAgICAgICAgcmVzb2x2ZVNjRXh0ZW5zaW9uKHNJbXBsLCBwYXJzZVNjLmdldEV4dGVuc2lvbigpKTsKICAgICAgICAgICAgZWxzZSBpZiAocGFyc2VTYy5nZXRSZXN0cmljdGlvbigpICE9IG51bGwpCiAgICAgICAgICAgICAgICByZXNvbHZlU2NSZXN0cmljdGlvbihzSW1wbCwgcGFyc2VTYy5nZXRSZXN0cmljdGlvbigpKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiTWlzc2luZyByZXN0cmljdGlvbiBvciBleHRlbnNpb24iLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19SRVNUUklDVElPTl9PUl9FWFRFTlNJT04sIHBhcnNlU2MpOwogICAgICAgICAgICAgICAgcmVzb2x2ZUVycm9yVHlwZShzSW1wbCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgICAgIHJlc29sdmVCYXNpY0NvbXBsZXhUeXBlKHNJbXBsKTsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCByZXNvbHZlRXJyb3JUeXBlKFNjaGVtYVR5cGVJbXBsIHNJbXBsKQogICAgewogICAgICAgIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCJUaGlzIHR5cGUgb2YgZXJyb3IgcmVjb3Zlcnkgbm90IHlldCBpbXBsZW1lbnRlZC4iKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTY2hlbWFUeXBlLlJlZltdIG1ha2VSZWZBcnJheShDb2xsZWN0aW9uIHR5cGVMaXN0KQogICAgewogICAgICAgIFNjaGVtYVR5cGUuUmVmW10gcmVzdWx0ID0gbmV3IFNjaGVtYVR5cGUuUmVmW3R5cGVMaXN0LnNpemUoKV07CiAgICAgICAgaW50IGogPSAwOwogICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHR5cGVMaXN0Lml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOyBqKyspCiAgICAgICAgICAgIHJlc3VsdFtqXSA9ICgoU2NoZW1hVHlwZSlpLm5leHQoKSkuZ2V0UmVmKCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCgogICAgc3RhdGljIHZvaWQgcmVzb2x2ZUJhc2ljQ29tcGxleFR5cGUoU2NoZW1hVHlwZUltcGwgc0ltcGwpCiAgICB7CiAgICAgICAgTGlzdCBhbm9ueW1vdXNUeXBlcyA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICBDb21wbGV4VHlwZSBwYXJzZVRyZWUgPSAoQ29tcGxleFR5cGUpc0ltcGwuZ2V0UGFyc2VPYmplY3QoKTsKICAgICAgICBTdHJpbmcgdGFyZ2V0TmFtZXNwYWNlID0gc0ltcGwuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgYm9vbGVhbiBjaGFtZWxlb24gPSAoc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkgIT0gbnVsbCk7CiAgICAgICAgR3JvdXAgcGFyc2VHcm91cCA9IGdldENvbnRlbnRNb2RlbChwYXJzZVRyZWUpOwoKICAgICAgICBpZiAoc0ltcGwuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICB7CiAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQSB0eXBlIHJlZGVmaW5pdGlvbiBtdXN0IGV4dGVuZCBvciByZXN0cmljdCB0aGUgb3JpZ2luYWwgZGVmaW5pdGlvbiBvZiB0aGUgdHlwZS4iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IG9oIHdlbGwuCiAgICAgICAgfQoKICAgICAgICBpbnQgcGFydGljbGVDb2RlID0gdHJhbnNsYXRlUGFydGljbGVDb2RlKHBhcnNlR3JvdXApOwoKICAgICAgICAvLyB1c2VkIHRvIGVuc3VyZSBjb25zaXN0ZW5jeSAoZG9lc24ndCBiZWNvbWUgcGFydCBvZiB0aGUgcmVzdWx0KQogICAgICAgIE1hcCBlbGVtZW50TW9kZWwgPSBuZXcgU2VxdWVuY2VkSGFzaE1hcCgpOwoKICAgICAgICAvLyBidWlsZCBjb250ZW50IG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwgPSB0cmFuc2xhdGVDb250ZW50TW9kZWwoc0ltcGwsIHBhcnNlR3JvdXAsIHRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCBwYXJ0aWNsZUNvZGUsIGFub255bW91c1R5cGVzLCBlbGVtZW50TW9kZWwsIGZhbHNlLCBudWxsKTsKCiAgICAgICAgLy8gZGV0ZWN0IHRoZSBub25lbXB0eSAiYWxsIiBjYXNlIChlbXB0eSA8YWxsPiBkb2Vzbid0IGNvdW50IC0gaXQgbmVlZHMgdG8gYmUgZWxpbWluYXRlZCB0byBtYXRjaCBYU0QgdGVzdCBjYXNlcykKICAgICAgICBib29sZWFuIGlzQWxsID0gY29udGVudE1vZGVsICE9IG51bGwgJiYgY29udGVudE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkFMTDsKICAgICAgICAKICAgICAgICAvLyBidWlsZCBhdHRyIG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCgpOwogICAgICAgIHRyYW5zbGF0ZUF0dHJpYnV0ZU1vZGVsKHBhcnNlVHJlZSwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBzSW1wbCwgbnVsbCwgYXR0ck1vZGVsLCBudWxsLCB0cnVlLCBudWxsKTsKCiAgICAgICAgLy8gc3VtbWFyaXplIHdpbGRjYXJkIGluZm9ybWF0aW9uCiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NFbHQgPSBzdW1tYXJpemVFbHRXaWxkY2FyZHMoY29udGVudE1vZGVsKTsKICAgICAgICBXaWxkY2FyZFJlc3VsdCB3Y0F0dHIgPSBzdW1tYXJpemVBdHRyV2lsZGNhcmRzKGF0dHJNb2RlbCk7CgogICAgICAgIC8vIGJ1aWxkIHN0YXRlIG1hY2hpbmUgYW5kIHZlcmlmeSB0aGF0IGNvbnRlbnQgbW9kZWwgaXMgZGV0ZXJtaW5pc3RpYwogICAgICAgIGlmIChjb250ZW50TW9kZWwgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGJ1aWxkU3RhdGVNYWNoaW5lKGNvbnRlbnRNb2RlbCk7CiAgICAgICAgICAgIGlmICghU3RzY1N0YXRlLmdldCgpLm5vVXBhKCkgJiYgISgoU2NoZW1hUGFydGljbGVJbXBsKWNvbnRlbnRNb2RlbCkuaXNEZXRlcm1pbmlzdGljKCkpCiAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIkNvbnRlbnQgbW9kZWwgdmlvbGF0ZXMgdGhlIHVuaXF1ZSBwYXJ0aWNsZSBhdHRyaWJ1dGlvbiBydWxlIiwgWG1sRXJyb3JDb250ZXh0Lk5PTkRFVEVSTUlOSVNUSUNfTU9ERUwsIHBhcnNlR3JvdXApOwogICAgICAgIH0KCiAgICAgICAgLy8gYnVpbGQgcHJvcGVydHkgbW9kZWwKICAgICAgICAvLyBlbWl0REJHKCJCdWlsZGluZyBjb250ZW50IE1vZGVsIGZvciAiICsgc0ltcGwpOwogICAgICAgIE1hcCBlbGVtZW50UHJvcGVydHlNb2RlbCA9IGJ1aWxkQ29udGVudFByb3BlcnR5TW9kZWxCeVFOYW1lKGNvbnRlbnRNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBhZGQgYXR0cmlidXRlIHByb3BlcnR5IG1vZGVsCiAgICAgICAgTWFwIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwgPSBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKGF0dHJNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBmaWd1cmUgb3V0IGNvbnRlbnQgdHlwZQogICAgICAgIGludCBjb21wbGV4VmFyaWV0eSA9CiAgICAgICAgICAgIHBhcnNlVHJlZS5nZXRNaXhlZCgpCiAgICAgICAgICAgICAgICA/IFNjaGVtYVR5cGUuTUlYRURfQ09OVEVOVAogICAgICAgICAgICAgICAgOiBjb250ZW50TW9kZWwgPT0gbnVsbAogICAgICAgICAgICAgICAgICAgID8gU2NoZW1hVHlwZS5FTVBUWV9DT05URU5UCiAgICAgICAgICAgICAgICAgICAgOiBTY2hlbWFUeXBlLkVMRU1FTlRfQ09OVEVOVDsKCiAgICAgICAgLy8gbm93IGZpbGwgaW4gdGhlIGFjdHVhbCBzY2hlbWEgdHlwZSBpbXBsZW1lbnRhdGlvbgogICAgICAgIHNJbXBsLnNldEJhc2VUeXBlUmVmKEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9UWVBFLmdldFJlZigpKTsKICAgICAgICBzSW1wbC5zZXRCYXNlRGVwdGgoQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1RZUEUuZ2V0QmFzZURlcHRoKCkgKyAxKTsKICAgICAgICBzSW1wbC5zZXREZXJpdmF0aW9uVHlwZShTY2hlbWFUeXBlLkRUX0VYVEVOU0lPTik7CiAgICAgICAgc0ltcGwuc2V0Q29tcGxleFR5cGVWYXJpZXR5KGNvbXBsZXhWYXJpZXR5KTsKICAgICAgICBzSW1wbC5zZXRDb250ZW50TW9kZWwoY29udGVudE1vZGVsLCBhdHRyTW9kZWwsIGVsZW1lbnRQcm9wZXJ0eU1vZGVsLCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsLCBpc0FsbCk7CiAgICAgICAgc0ltcGwuc2V0QW5vbnltb3VzVHlwZVJlZnMobWFrZVJlZkFycmF5KGFub255bW91c1R5cGVzKSk7CiAgICAgICAgc0ltcGwuc2V0V2lsZGNhcmRTdW1tYXJ5KHdjRWx0LnR5cGVkV2lsZGNhcmRzLCB3Y0VsdC5oYXNXaWxkY2FyZHMsIHdjQXR0ci50eXBlZFdpbGRjYXJkcywgd2NBdHRyLmhhc1dpbGRjYXJkcyk7CiAgICB9CgogICAgc3RhdGljIHZvaWQgcmVzb2x2ZUNjUmVzdHJpY3Rpb24oU2NoZW1hVHlwZUltcGwgc0ltcGwsIENvbXBsZXhSZXN0cmljdGlvblR5cGUgcGFyc2VUcmVlLCBib29sZWFuIG1peGVkKQogICAgewogICAgICAgIFN0c2NTdGF0ZSBzdGF0ZSA9IFN0c2NTdGF0ZS5nZXQoKTsKICAgICAgICBTdHJpbmcgdGFyZ2V0TmFtZXNwYWNlID0gc0ltcGwuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgYm9vbGVhbiBjaGFtZWxlb24gPSAoc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkgIT0gbnVsbCk7CgogICAgICAgIC8vIEJVR0JVRzogTk9UIFlFVCBSRUFMTFkgSU1QTEVNRU5URUQKICAgICAgICAvLyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigiTm90IHlldCBpbXBsZW1lbnRlZC4iKTsKCiAgICAgICAgU2NoZW1hVHlwZSBiYXNlVHlwZTsKICAgICAgICBpZiAocGFyc2VUcmVlLmdldEJhc2UoKSA9PSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgY29tcGxleENvbnRlbnQgbXVzdCBkZWZpbmUgYSBiYXNlIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19CQVNFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICBiYXNlVHlwZSA9IG51bGw7IC8vIHJlY292ZXJ5OiBubyBpbmhlcml0YW5jZS4KICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHNJbXBsLmlzUmVkZWZpbml0aW9uKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gc3RhdGUuZmluZFJlZGVmaW5lZEdsb2JhbFR5cGUocGFyc2VUcmVlLmdldEJhc2UoKSwgc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCksIHNJbXBsLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiAhYmFzZVR5cGUuZ2V0TmFtZSgpLmVxdWFscyhzSW1wbC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgcmVkZWZpbml0aW9uIG11c3QgZXh0ZW5kIHRoZSBvcmlnaW5hbCB0eXBlIGRlZmluaXRpb24iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gc3RhdGUuZmluZEdsb2JhbFR5cGUocGFyc2VUcmVlLmdldEJhc2UoKSwgc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIAogICAgICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocGFyc2VUcmVlLmdldEJhc2UoKSwgWG1sRXJyb3JDb250ZXh0LlRZUEVfTk9UX0ZPVU5ELCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfVFlQRTsKCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgYmFzZVR5cGUuZmluYWxSZXN0cmljdGlvbigpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkNhbm5vdCByZXN0cmljdCBhIGZpbmFsIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuQ0FOTk9UX0RFUklWRV9GSU5BTCwgcGFyc2VUcmVlLnhnZXRCYXNlKCkpOwogICAgICAgICAgICAvLyByZWNvdmVyeToganVzdCBrZWVwIGdvaW5nCiAgICAgICAgfQoKICAgICAgICAvLyBSZWN1cnNpb24KICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGlmICghU3RzY1Jlc29sdmVyLnJlc29sdmVUeXBlKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSkpCiAgICAgICAgICAgICAgICBiYXNlVHlwZSA9IG51bGw7IC8vIGNpcmN1bGFyIGRlcGVuZGVuY3k6IG5vIGluaGVyaXRhbmNlCiAgICAgICAgfQoKICAgICAgICBMaXN0IGFub255bW91c1R5cGVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIEdyb3VwIHBhcnNlRWcgPSBnZXRDb250ZW50TW9kZWwocGFyc2VUcmVlKTsKCiAgICAgICAgLy8gZGV0ZWN0IHRoZSAiYWxsIiBjYXNlCiAgICAgICAgaW50IHBhcnRpY2xlQ29kZSA9IHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShwYXJzZUVnKTsKCiAgICAgICAgLy8gdXNlZCB0byBlbnN1cmUgY29uc2lzdGVuY3kgKGRvZXNuJ3QgYmVjb21lIHBhcnQgb2YgdGhlIHJlc3VsdCkKICAgICAgICBNYXAgZWxlbWVudE1vZGVsID0gbmV3IFNlcXVlbmNlZEhhc2hNYXAoKTsKCiAgICAgICAgLy8gYnVpbGQgY29udGVudCBtb2RlbCBhbmQgYW5vbnltb3VzIHR5cGVzCiAgICAgICAgU2NoZW1hUGFydGljbGUgY29udGVudE1vZGVsID0gdHJhbnNsYXRlQ29udGVudE1vZGVsKAogICAgICAgICAgICBzSW1wbCwgcGFyc2VFZywgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIHBhcnRpY2xlQ29kZSwgYW5vbnltb3VzVHlwZXMsIGVsZW1lbnRNb2RlbCwgZmFsc2UsIG51bGwpOwoKICAgICAgICAvLyBkZXRlY3QgdGhlIG5vbmVtcHR5ICJhbGwiIGNhc2UgKGVtcHR5IDxhbGw+IGRvZXNuJ3QgY291bnQgLSBpdCBuZWVkcyB0byBiZSBlbGltaW5hdGVkIHRvIG1hdGNoIFhTRCB0ZXN0IGNhc2VzKQogICAgICAgIGJvb2xlYW4gaXNBbGwgPSBjb250ZW50TW9kZWwgIT0gbnVsbCAmJiBjb250ZW50TW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMOwogICAgICAgIAogICAgICAgIC8vIGJ1aWxkIGF0dHIgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCBhdHRyTW9kZWw7CiAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgIGF0dHJNb2RlbCA9IG5ldyBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwoKTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIGF0dHJNb2RlbCA9IG5ldyBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwoYmFzZVR5cGUuZ2V0QXR0cmlidXRlTW9kZWwoKSk7CiAgICAgICAgdHJhbnNsYXRlQXR0cmlidXRlTW9kZWwocGFyc2VUcmVlLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIHNJbXBsLCBudWxsLCBhdHRyTW9kZWwsIGJhc2VUeXBlLCBmYWxzZSwgbnVsbCk7CgogICAgICAgIC8vIHN1bW1hcml6ZSB3aWxkY2FyZCBpbmZvcm1hdGlvbgogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjRWx0ID0gc3VtbWFyaXplRWx0V2lsZGNhcmRzKGNvbnRlbnRNb2RlbCk7CiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NBdHRyID0gc3VtbWFyaXplQXR0cldpbGRjYXJkcyhhdHRyTW9kZWwpOwoKICAgICAgICAvLyBidWlsZCBzdGF0ZSBtYWNoaW5lIGFuZCB2ZXJpZnkgdGhhdCBjb250ZW50IG1vZGVsIGlzIGRldGVybWluaXN0aWMKICAgICAgICBpZiAoY29udGVudE1vZGVsICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBidWlsZFN0YXRlTWFjaGluZShjb250ZW50TW9kZWwpOwogICAgICAgICAgICBpZiAoIVN0c2NTdGF0ZS5nZXQoKS5ub1VwYSgpICYmICEoKFNjaGVtYVBhcnRpY2xlSW1wbCljb250ZW50TW9kZWwpLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJDb250ZW50IG1vZGVsIHZpb2xhdGVzIHRoZSB1bmlxdWUgcGFydGljbGUgYXR0cmlidXRpb24gcnVsZSIsIFhtbEVycm9yQ29udGV4dC5OT05ERVRFUk1JTklTVElDX01PREVMLCBwYXJzZUVnKTsKICAgICAgICB9CgogICAgICAgIC8vIGJ1aWxkIHByb3BlcnR5IG1vZGVsCiAgICAgICAgLy8gZW1pdERCRygiQnVpbGRpbmcgY29udGVudCBNb2RlbCBmb3IgIiArIHNJbXBsKTsKICAgICAgICBNYXAgZWxlbWVudFByb3BlcnR5TW9kZWwgPSBidWlsZENvbnRlbnRQcm9wZXJ0eU1vZGVsQnlRTmFtZShjb250ZW50TW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gYWRkIGF0dHJpYnV0ZSBwcm9wZXJ0eSBtb2RlbAogICAgICAgIE1hcCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsID0gYnVpbGRBdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsQnlRTmFtZShhdHRyTW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gY29tcHV0ZSBlbXB0eS9lbGVtZW50L21peGVkCiAgICAgICAgaW50IGNvbXBsZXhWYXJpZXR5ID0gKGNvbnRlbnRNb2RlbCA9PSBudWxsID8gU2NoZW1hVHlwZS5FTVBUWV9DT05URU5UIDoKICAgICAgICAgICAgKG1peGVkID8gU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UIDogU2NoZW1hVHlwZS5FTEVNRU5UX0NPTlRFTlQpKTsKCiAgICAgICAgLy8gbm93IGZpbGwgaW4gdGhlIGFjdHVhbCBzY2hlbWEgdHlwZSBpbXBsZW1lbnRhdGlvbgogICAgICAgIHNJbXBsLnNldEJhc2VUeXBlUmVmKGJhc2VUeXBlLmdldFJlZigpKTsKICAgICAgICBzSW1wbC5zZXRCYXNlRGVwdGgoKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSkuZ2V0QmFzZURlcHRoKCkgKyAxKTsKICAgICAgICBzSW1wbC5zZXREZXJpdmF0aW9uVHlwZShTY2hlbWFUeXBlLkRUX1JFU1RSSUNUSU9OKTsKICAgICAgICBzSW1wbC5zZXRDb21wbGV4VHlwZVZhcmlldHkoY29tcGxleFZhcmlldHkpOwogICAgICAgIHNJbXBsLnNldENvbnRlbnRNb2RlbChjb250ZW50TW9kZWwsIGF0dHJNb2RlbCwgZWxlbWVudFByb3BlcnR5TW9kZWwsIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwsIGlzQWxsKTsKICAgICAgICBzSW1wbC5zZXRBbm9ueW1vdXNUeXBlUmVmcyhtYWtlUmVmQXJyYXkoYW5vbnltb3VzVHlwZXMpKTsKICAgICAgICBzSW1wbC5zZXRXaWxkY2FyZFN1bW1hcnkod2NFbHQudHlwZWRXaWxkY2FyZHMsIHdjRWx0Lmhhc1dpbGRjYXJkcywgd2NBdHRyLnR5cGVkV2lsZGNhcmRzLCB3Y0F0dHIuaGFzV2lsZGNhcmRzKTsKICAgIH0KCiAgICBzdGF0aWMgTWFwIGV4dHJhY3RFbGVtZW50TW9kZWwoU2NoZW1hVHlwZSBzVHlwZSkKICAgIHsKICAgICAgICBNYXAgZWxlbWVudE1vZGVsID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBpZiAoc1R5cGUgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYVByb3BlcnR5W10gc1Byb3BzID0gc1R5cGUuZ2V0UHJvcGVydGllcygpOwogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHNQcm9wcy5sZW5ndGg7IGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKHNQcm9wc1tpXS5pc0F0dHJpYnV0ZSgpKQogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgZWxlbWVudE1vZGVsLnB1dChzUHJvcHNbaV0uZ2V0TmFtZSgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzUHJvcHNbaV0uZ2V0VHlwZSgpKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gZWxlbWVudE1vZGVsOwogICAgfQoKICAgIHN0YXRpYyB2b2lkIHJlc29sdmVDY0V4dGVuc2lvbihTY2hlbWFUeXBlSW1wbCBzSW1wbCwgRXh0ZW5zaW9uVHlwZSBwYXJzZVRyZWUsIGJvb2xlYW4gbWl4ZWQpCiAgICB7CiAgICAgICAgU2NoZW1hVHlwZSBiYXNlVHlwZTsKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CiAgICAgICAgU3RyaW5nIHRhcmdldE5hbWVzcGFjZSA9IHNJbXBsLmdldFRhcmdldE5hbWVzcGFjZSgpOwogICAgICAgIGJvb2xlYW4gY2hhbWVsZW9uID0gKHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpICE9IG51bGwpOwoKICAgICAgICBpZiAocGFyc2VUcmVlLmdldEJhc2UoKSA9PSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgY29tcGxleENvbnRlbnQgbXVzdCBkZWZpbmUgYSBiYXNlIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19CQVNFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICBiYXNlVHlwZSA9IG51bGw7IC8vIHJlY292ZXJ5OiBubyBpbmhlcml0YW5jZS4KICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHNJbXBsLmlzUmVkZWZpbml0aW9uKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gc3RhdGUuZmluZFJlZGVmaW5lZEdsb2JhbFR5cGUocGFyc2VUcmVlLmdldEJhc2UoKSwgc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCksIHNJbXBsLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiAhYmFzZVR5cGUuZ2V0TmFtZSgpLmVxdWFscyhzSW1wbC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgcmVkZWZpbml0aW9uIG11c3QgZXh0ZW5kIHRoZSBvcmlnaW5hbCB0eXBlIGRlZmluaXRpb24iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gc3RhdGUuZmluZEdsb2JhbFR5cGUocGFyc2VUcmVlLmdldEJhc2UoKSwgc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChiYXNlVHlwZSA9PSBudWxsKQogICAgICAgICAgICAgICAgc3RhdGUubm90Rm91bmRFcnJvcihwYXJzZVRyZWUuZ2V0QmFzZSgpLCBYbWxFcnJvckNvbnRleHQuVFlQRV9OT1RfRk9VTkQsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICB9CgogICAgICAgIC8vIFJlY3Vyc2lvbgogICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCFTdHNjUmVzb2x2ZXIucmVzb2x2ZVR5cGUoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKSkKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gbnVsbDsgLy8gY2lyY3VsYXIgZGVwZW5kZW5jeTogbm8gaW5oZXJpdGFuY2UKICAgICAgICB9CgogICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmIChiYXNlVHlwZS5pc1NpbXBsZVR5cGUoKSB8fCBiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpID09IFNjaGVtYVR5cGUuU0lNUExFX0NPTlRFTlQpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlRoZSBzcGVjaWZpZWQgYmFzZSB0eXBlIGlzIG5vdCBhIGNvbXBsZXggdHlwZSB3aXRoIGNvbXBsZXggY29udGVudC4iLCBYbWxFcnJvckNvbnRleHQuQ09NUExFWF9CQVNFX05PVF9DT01QTEVYLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIGJhc2VUeXBlID0gbnVsbDsgLy8gcmVjb3Zlcnk6IG5vIGluaGVyaXRhbmNlLgogICAgICAgIH0KCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgYmFzZVR5cGUuZmluYWxFeHRlbnNpb24oKSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJDYW5ub3QgZXh0ZW5kIGEgZmluYWwgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBqdXN0IGtlZXAgZ29pbmcKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy8gZ2V0IGJhc2UgY29udGVudCBtb2RlbAogICAgICAgIFNjaGVtYVBhcnRpY2xlIGJhc2VDb250ZW50TW9kZWwgPSAoYmFzZVR5cGUgPT0gbnVsbCA/IG51bGwgOiBiYXNlVHlwZS5nZXRDb250ZW50TW9kZWwoKSk7CiAgICAgICAgLy8gVE9ETzogYXR0cmlidXRlIG1vZGVsIGFsc28KCiAgICAgICAgTGlzdCBhbm9ueW1vdXNUeXBlcyA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICBNYXAgYmFzZUVsZW1lbnRNb2RlbCA9IGV4dHJhY3RFbGVtZW50TW9kZWwoYmFzZVR5cGUpOwogICAgICAgIEdyb3VwIHBhcnNlRWcgPSBnZXRDb250ZW50TW9kZWwocGFyc2VUcmVlKTsKICAgICAgICAKICAgICAgICAvLyBidWlsZCBleHRlbnNpb24gbW9kZWwKICAgICAgICBTY2hlbWFQYXJ0aWNsZSBleHRlbnNpb25Nb2RlbCA9IHRyYW5zbGF0ZUNvbnRlbnRNb2RlbCgKICAgICAgICAgICAgICAgIHNJbXBsLCBwYXJzZUVnLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgdHJhbnNsYXRlUGFydGljbGVDb2RlKHBhcnNlRWcpLAogICAgICAgICAgICAgICAgYW5vbnltb3VzVHlwZXMsIGJhc2VFbGVtZW50TW9kZWwsIGZhbHNlLCBudWxsKTsKICAgICAgICAKICAgICAgICAvLyBhcHBseSBydWxlICMyIG5lYXIgaHR0cDovL3d3dy53My5vcmcvVFIveG1sc2NoZW1hLTEvI2MtbXZlOiBlbXB0eSBleHQgbW9kZWwgLT4gbWl4ZWQgdGFrZW4gZnJvbSBiYXNlCiAgICAgICAgaWYgKGV4dGVuc2lvbk1vZGVsID09IG51bGwgJiYgIW1peGVkKQogICAgICAgICAgICBtaXhlZCA9IChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpID09IFNjaGVtYVR5cGUuTUlYRURfQ09OVEVOVCk7CiAgICAgICAgCiAgICAgICAgLy8gYXBwbHkgRGVyaXZhdGlvbiBWYWxpZCAoRXh0ZW5zaW9uKSBydWxlIDEuNC4yLjIKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiAoYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSAhPSBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQpICYmCiAgICAgICAgICAgICAgICAoKGJhc2VUeXBlLmdldENvbnRlbnRUeXBlKCkgPT0gU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UKSAhPSBtaXhlZCkpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQ2Fubm90IGV4dGVuZCBhbiBlbGVtZW50LW9ubHkgdHlwZSB3aXRoIGEgbWl4ZWQgdHlwZSBvciB2aWNlLXZlcnNhIiwgWG1sRXJyb3JDb250ZXh0LklOQ09OU0lTVEVOVF9UWVBFLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBqdXN0IGtlZXAgZ29pbmcKICAgICAgICB9CgogICAgICAgIC8vIGRldGVjdCB0aGUgImFsbCIgYmFzZSBjYXNlCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgYmFzZVR5cGUuaGFzQWxsQ29udGVudCgpICYmIGV4dGVuc2lvbk1vZGVsICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQ2Fubm90IGV4dGVuZCBhIHR5cGUgd2l0aCAnYWxsJyBjb250ZW50IG1vZGVsIiwgWG1sRXJyb3JDb250ZXh0LkNBTk5PVF9FWFRFTkRfQUxMLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIGV4dGVuc2lvbk1vZGVsID0gbnVsbDsgLy8gcmVjb3Zlcnk6IGRyb3AgZXh0ZW5zaW9uCiAgICAgICAgfQoKICAgICAgICAvLyBidWlsZCBjb250ZW50IG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwgPSBleHRlbmRDb250ZW50TW9kZWwoYmFzZUNvbnRlbnRNb2RlbCwgZXh0ZW5zaW9uTW9kZWwsIHBhcnNlVHJlZSk7CgogICAgICAgIC8vIGRldGVjdCB0aGUgbm9uZW1wdHkgImFsbCIgY2FzZSAoZW1wdHkgPGFsbD4gZG9lc24ndCBjb3VudCAtIGl0IG5lZWRzIHRvIGJlIGVsaW1pbmF0ZWQgdG8gbWF0Y2ggWFNEIHRlc3QgY2FzZXMpCiAgICAgICAgYm9vbGVhbiBpc0FsbCA9IGNvbnRlbnRNb2RlbCAhPSBudWxsICYmIGNvbnRlbnRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5BTEw7CiAgICAgICAgCiAgICAgICAgLy8gYnVpbGQgYXR0ciBtb2RlbCBhbmQgYW5vbnltb3VzIHR5cGVzCiAgICAgICAgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsIGF0dHJNb2RlbDsKICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCgpOwogICAgICAgIGVsc2UKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbChiYXNlVHlwZS5nZXRBdHRyaWJ1dGVNb2RlbCgpKTsKICAgICAgICB0cmFuc2xhdGVBdHRyaWJ1dGVNb2RlbChwYXJzZVRyZWUsIHRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCBhbm9ueW1vdXNUeXBlcywgc0ltcGwsIG51bGwsIGF0dHJNb2RlbCwgYmFzZVR5cGUsIHRydWUsIG51bGwpOwoKICAgICAgICAvLyBzdW1tYXJpemUgd2lsZGNhcmQgaW5mb3JtYXRpb24KICAgICAgICBXaWxkY2FyZFJlc3VsdCB3Y0VsdCA9IHN1bW1hcml6ZUVsdFdpbGRjYXJkcyhjb250ZW50TW9kZWwpOwogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjQXR0ciA9IHN1bW1hcml6ZUF0dHJXaWxkY2FyZHMoYXR0ck1vZGVsKTsKCiAgICAgICAgLy8gYnVpbGQgc3RhdGUgbWFjaGluZSBhbmQgdmVyaWZ5IHRoYXQgY29udGVudCBtb2RlbCBpcyBkZXRlcm1pbmlzdGljCiAgICAgICAgaWYgKGNvbnRlbnRNb2RlbCAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgYnVpbGRTdGF0ZU1hY2hpbmUoY29udGVudE1vZGVsKTsKICAgICAgICAgICAgaWYgKCFTdHNjU3RhdGUuZ2V0KCkubm9VcGEoKSAmJiAhKChTY2hlbWFQYXJ0aWNsZUltcGwpY29udGVudE1vZGVsKS5pc0RldGVybWluaXN0aWMoKSkKICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQ29udGVudCBtb2RlbCB2aW9sYXRlcyB0aGUgdW5pcXVlIHBhcnRpY2xlIGF0dHJpYnV0aW9uIHJ1bGUiLCBYbWxFcnJvckNvbnRleHQuTk9OREVURVJNSU5JU1RJQ19NT0RFTCwgcGFyc2VFZyk7CiAgICAgICAgfQoKICAgICAgICAvLyBidWlsZCBwcm9wZXJ0eSBtb2RlbAogICAgICAgIC8vIGVtaXREQkcoIkJ1aWxkaW5nIGNvbnRlbnQgTW9kZWwgZm9yICIgKyBzSW1wbCk7CiAgICAgICAgTWFwIGVsZW1lbnRQcm9wZXJ0eU1vZGVsID0gYnVpbGRDb250ZW50UHJvcGVydHlNb2RlbEJ5UU5hbWUoY29udGVudE1vZGVsLCBzSW1wbCk7CgogICAgICAgIC8vIGFkZCBhdHRyaWJ1dGUgcHJvcGVydHkgbW9kZWwKICAgICAgICBNYXAgYXR0cmlidXRlUHJvcGVydHlNb2RlbCA9IGJ1aWxkQXR0cmlidXRlUHJvcGVydHlNb2RlbEJ5UU5hbWUoYXR0ck1vZGVsLCBzSW1wbCk7CgogICAgICAgIC8vIGNvbXB1dGUgZW1wdHkvZWxlbWVudC9taXhlZAogICAgICAgIGludCBjb21wbGV4VmFyaWV0eSA9ICAoIG1peGVkID8gU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UIDoKICAgICAgICAgICAgKGNvbnRlbnRNb2RlbCA9PSBudWxsID8gU2NoZW1hVHlwZS5FTVBUWV9DT05URU5UIDogU2NoZW1hVHlwZS5FTEVNRU5UX0NPTlRFTlQpKTsKCiAgICAgICAgLy8gbm93IGZpbGwgaW4gdGhlIGFjdHVhbCBzY2hlbWEgdHlwZSBpbXBsZW1lbnRhdGlvbgogICAgICAgIGlmIChiYXNlVHlwZSA9PSBudWxsKQogICAgICAgICAgICBiYXNlVHlwZSA9IFhtbE9iamVjdC50eXBlOwogICAgICAgIHNJbXBsLnNldEJhc2VUeXBlUmVmKGJhc2VUeXBlLmdldFJlZigpKTsKICAgICAgICBzSW1wbC5zZXRCYXNlRGVwdGgoKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSkuZ2V0QmFzZURlcHRoKCkgKyAxKTsKICAgICAgICBzSW1wbC5zZXREZXJpdmF0aW9uVHlwZShTY2hlbWFUeXBlLkRUX0VYVEVOU0lPTik7CiAgICAgICAgc0ltcGwuc2V0Q29tcGxleFR5cGVWYXJpZXR5KGNvbXBsZXhWYXJpZXR5KTsKICAgICAgICBzSW1wbC5zZXRDb250ZW50TW9kZWwoY29udGVudE1vZGVsLCBhdHRyTW9kZWwsIGVsZW1lbnRQcm9wZXJ0eU1vZGVsLCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsLCBpc0FsbCk7CiAgICAgICAgc0ltcGwuc2V0QW5vbnltb3VzVHlwZVJlZnMobWFrZVJlZkFycmF5KGFub255bW91c1R5cGVzKSk7CiAgICAgICAgc0ltcGwuc2V0V2lsZGNhcmRTdW1tYXJ5KHdjRWx0LnR5cGVkV2lsZGNhcmRzLCB3Y0VsdC5oYXNXaWxkY2FyZHMsIHdjQXR0ci50eXBlZFdpbGRjYXJkcywgd2NBdHRyLmhhc1dpbGRjYXJkcyk7CiAgICB9CgogICAgc3RhdGljIHZvaWQgcmVzb2x2ZVNjUmVzdHJpY3Rpb24oU2NoZW1hVHlwZUltcGwgc0ltcGwsIFNpbXBsZVJlc3RyaWN0aW9uVHlwZSBwYXJzZVRyZWUpCiAgICB7CiAgICAgICAgU2NoZW1hVHlwZSBiYXNlVHlwZTsKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CiAgICAgICAgU3RyaW5nIHRhcmdldE5hbWVzcGFjZSA9IHNJbXBsLmdldFRhcmdldE5hbWVzcGFjZSgpOwogICAgICAgIGJvb2xlYW4gY2hhbWVsZW9uID0gKHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpICE9IG51bGwpOwogICAgICAgIGlmIChwYXJzZVRyZWUuZ2V0U2ltcGxlVHlwZSgpICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS53YXJuaW5nKCJOZXN0ZWQgc2ltcGxlIHR5cGVzIGluc2lkZSBzaW1wbGUgY29udGVudCByZXN0cmljdGlvbnMgYXJlIHVuc3VwcG9ydGVkIC0gaWdub3JpbmciLCBYbWxFcnJvckNvbnRleHQuSUxMRUdBTF9SRVNUUklDVElPTiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGlnbm9yZSB0aGUgbmVzdGVkIHNpbXBsZSB0eXBlIGVsZW1lbnQuCiAgICAgICAgfQogICAgICAgIGlmIChwYXJzZVRyZWUuZ2V0QmFzZSgpID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSBzaW1wbGVDb250ZW50IHJlc3RyaWN0aW9uIG11c3QgZGVmaW5lIGEgYmFzZSB0eXBlIiwgWG1sRXJyb3JDb250ZXh0Lk1JU1NJTkdfQkFTRSwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGV4dGVuZHMgQU5ZX1NJTVBMRSB0eXBlCiAgICAgICAgICAgIGJhc2VUeXBlID0gQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1NJTVBMRTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHNJbXBsLmlzUmVkZWZpbml0aW9uKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gc3RhdGUuZmluZFJlZGVmaW5lZEdsb2JhbFR5cGUocGFyc2VUcmVlLmdldEJhc2UoKSwgc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCksIHNJbXBsLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiAhYmFzZVR5cGUuZ2V0TmFtZSgpLmVxdWFscyhzSW1wbC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHR5cGUgcmVkZWZpbml0aW9uIG11c3QgcmVzdHJpY3QgdGhlIG9yaWdpbmFsIHR5cGUgZGVmaW5pdGlvbiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocGFyc2VUcmVlLmdldEJhc2UoKSwgWG1sRXJyb3JDb250ZXh0LlRZUEVfTk9UX0ZPVU5ELCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1NJTVBMRTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gUmVjdXJzaW9uCiAgICAgICAgU3RzY1Jlc29sdmVyLnJlc29sdmVUeXBlKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSk7CgogICAgICAgIGlmIChiYXNlVHlwZS5pc1NpbXBsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJTaW1wbGUgdHlwZSAnIiArIGJhc2VUeXBlLmdldE5hbWUoKSArICInIGNhbm5vdCBiZSB1c2VkIGFzIHRoZSBiYXNlIHR5cGUgb2YgYSBzaW1wbGUgY29udGVudCByZXN0cmljdGlvbi4gKFVzZSBleHRlbnNpb24gaW5zdGVhZC4pIiwgWG1sRXJyb3JDb250ZXh0LlNJTVBMRV9CQVNFX05PVF9TSU1QTEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICBiYXNlVHlwZSA9IEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9TSU1QTEU7CiAgICAgICAgfQogICAgICAgIC8vIEJVR0JVRzogY2FuIHJlc3RyaWN0IG1peGVkIGNvbnRlbnQgYXMgbG9uZyBhcyBhbGwgY2hpbGQgZWxlbWVudHMgYXJlIG9wdGlvbmFsCiAgICAgICAgZWxzZSBpZiAoYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSAhPSBTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlRoZSBzcGVjaWZpZWQgYmFzZSB0eXBlICIgKyBiYXNlVHlwZS50b1N0cmluZygpICsgIiBkb2VzIG5vdCBoYXZlIHNpbXBsZSBjb250ZW50LiIsIFhtbEVycm9yQ29udGV4dC5TSU1QTEVfQkFTRV9OT1RfU0lNUExFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgIH0KCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgYmFzZVR5cGUuZmluYWxSZXN0cmljdGlvbigpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkNhbm5vdCByZXN0cmljdCBhIGZpbmFsIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuQ0FOTk9UX0RFUklWRV9GSU5BTCwgcGFyc2VUcmVlLnhnZXRCYXNlKCkpOwogICAgICAgICAgICAvLyByZWNvdmVyeToganVzdCBrZWVwIGdvaW5nCiAgICAgICAgfQoKICAgICAgICAvLyBidWlsZCBhdHRyIG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBMaXN0IGFub255bW91c1R5cGVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCBhdHRyTW9kZWw7CiAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgIGF0dHJNb2RlbCA9IG5ldyBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwoKTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIGF0dHJNb2RlbCA9IG5ldyBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwoYmFzZVR5cGUuZ2V0QXR0cmlidXRlTW9kZWwoKSk7CiAgICAgICAgdHJhbnNsYXRlQXR0cmlidXRlTW9kZWwocGFyc2VUcmVlLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIHNJbXBsLCBudWxsLCBhdHRyTW9kZWwsIGJhc2VUeXBlLCBmYWxzZSwgbnVsbCk7CgogICAgICAgIC8vIHN1bW1hcml6ZSB3aWxkY2FyZCBpbmZvcm1hdGlvbgogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjQXR0ciA9IHN1bW1hcml6ZUF0dHJXaWxkY2FyZHMoYXR0ck1vZGVsKTsKCiAgICAgICAgLy8gYWRkIGF0dHJpYnV0ZSBwcm9wZXJ0eSBtb2RlbAogICAgICAgIE1hcCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsID0gYnVpbGRBdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsQnlRTmFtZShhdHRyTW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gbm93IGZpbGwgaW4gdGhlIGFjdHVhbCBzY2hlbWEgdHlwZSBpbXBsZW1lbnRhdGlvbgogICAgICAgIHNJbXBsLnNldEJhc2VUeXBlUmVmKGJhc2VUeXBlLmdldFJlZigpKTsKICAgICAgICBzSW1wbC5zZXRCYXNlRGVwdGgoKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSkuZ2V0QmFzZURlcHRoKCkgKyAxKTsKICAgICAgICBzSW1wbC5zZXREZXJpdmF0aW9uVHlwZShTY2hlbWFUeXBlLkRUX1JFU1RSSUNUSU9OKTsKICAgICAgICBzSW1wbC5zZXRBbm9ueW1vdXNUeXBlUmVmcyhtYWtlUmVmQXJyYXkoYW5vbnltb3VzVHlwZXMpKTsKICAgICAgICBzSW1wbC5zZXRXaWxkY2FyZFN1bW1hcnkoUU5hbWVTZXQuRU1QVFksIGZhbHNlLCB3Y0F0dHIudHlwZWRXaWxkY2FyZHMsIHdjQXR0ci5oYXNXaWxkY2FyZHMpOwogICAgICAgIHNJbXBsLnNldENvbXBsZXhUeXBlVmFyaWV0eShTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UKTsKICAgICAgICBzSW1wbC5zZXRDb250ZW50TW9kZWwobnVsbCwgYXR0ck1vZGVsLCBudWxsLCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsLCBmYWxzZSk7CiAgICAgICAgc0ltcGwuc2V0U2ltcGxlVHlwZVZhcmlldHkoYmFzZVR5cGUuZ2V0U2ltcGxlVmFyaWV0eSgpKTsKICAgICAgICBzSW1wbC5zZXRQcmltaXRpdmVUeXBlUmVmKGJhc2VUeXBlLmdldFByaW1pdGl2ZVR5cGUoKSA9PSBudWxsID8gbnVsbCA6IGJhc2VUeXBlLmdldFByaW1pdGl2ZVR5cGUoKS5nZXRSZWYoKSk7CiAgICAgICAgc3dpdGNoIChzSW1wbC5nZXRTaW1wbGVWYXJpZXR5KCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuTElTVDoKICAgICAgICAgICAgICAgIHNJbXBsLnNldExpc3RJdGVtVHlwZVJlZihiYXNlVHlwZS5nZXRMaXN0SXRlbVR5cGUoKS5nZXRSZWYoKSk7CiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgU2NoZW1hVHlwZS5VTklPTjoKICAgICAgICAgICAgICAgIHNJbXBsLnNldFVuaW9uTWVtYmVyVHlwZVJlZnMobWFrZVJlZkFycmF5KEFycmF5cy5hc0xpc3QoYmFzZVR5cGUuZ2V0VW5pb25NZW1iZXJUeXBlcygpKSkpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICAvLyBkZWFsIHdpdGggZmFjZXRzCiAgICAgICAgU3RzY1NpbXBsZVR5cGVSZXNvbHZlci5yZXNvbHZlRmFjZXRzKHNJbXBsLCBwYXJzZVRyZWUsIChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSk7CgogICAgICAgIC8vIG5vdyBjb21wdXRlIG91ciBpbnRyaW5zaWMgcHJvcGVydGllcwogICAgICAgIFN0c2NTaW1wbGVUeXBlUmVzb2x2ZXIucmVzb2x2ZUZ1bmRhbWVudGFsRmFjZXRzKHNJbXBsKTsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCByZXNvbHZlU2NFeHRlbnNpb24oU2NoZW1hVHlwZUltcGwgc0ltcGwsIFNpbXBsZUV4dGVuc2lvblR5cGUgcGFyc2VUcmVlKQogICAgewogICAgICAgIFNjaGVtYVR5cGUgYmFzZVR5cGU7CiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwogICAgICAgIFN0cmluZyB0YXJnZXROYW1lc3BhY2UgPSBzSW1wbC5nZXRUYXJnZXROYW1lc3BhY2UoKTsKICAgICAgICBib29sZWFuIGNoYW1lbGVvbiA9IChzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSAhPSBudWxsKTsKICAgICAgICBpZiAocGFyc2VUcmVlLmdldEJhc2UoKSA9PSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgc2ltcGxlQ29udGVudCBleHRlbnNpb24gbXVzdCBkZWZpbmUgYSBiYXNlIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19CQVNFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoc0ltcGwuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kUmVkZWZpbmVkR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSwgc0ltcGwuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmICFiYXNlVHlwZS5nZXROYW1lKCkuZXF1YWxzKHNJbXBsLmdldE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgdHlwZSByZWRlZmluaXRpb24gbXVzdCBleHRlbmQgdGhlIG9yaWdpbmFsIHR5cGUgZGVmaW5pdGlvbiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocGFyc2VUcmVlLmdldEJhc2UoKSwgWG1sRXJyb3JDb250ZXh0LlRZUEVfTk9UX0ZPVU5ELCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1NJTVBMRTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gUmVjdXJzaW9uCiAgICAgICAgU3RzY1Jlc29sdmVyLnJlc29sdmVUeXBlKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSk7CgogICAgICAgIGlmICghYmFzZVR5cGUuaXNTaW1wbGVUeXBlKCkgJiYgYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSAhPSBTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlRoZSBzcGVjaWZpZWQgYmFzZSB0eXBlICIgKyBiYXNlVHlwZS50b1N0cmluZygpICsgIiBkb2VzIG5vdCBoYXZlIHNpbXBsZSBjb250ZW50LiIsIFhtbEVycm9yQ29udGV4dC5TSU1QTEVfQkFTRV9OT1RfU0lNUExFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgIH0KCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgYmFzZVR5cGUuZmluYWxFeHRlbnNpb24oKSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJDYW5ub3QgZXh0ZW5kIGEgZmluYWwgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBqdXN0IGtlZXAgZ29pbmcKICAgICAgICB9CgogICAgICAgIC8vIGJ1aWxkIGF0dHIgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIExpc3QgYW5vbnltb3VzVHlwZXMgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsIGF0dHJNb2RlbDsKICAgICAgICBhdHRyTW9kZWwgPSBuZXcgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsKGJhc2VUeXBlLmdldEF0dHJpYnV0ZU1vZGVsKCkpOwogICAgICAgIHRyYW5zbGF0ZUF0dHJpYnV0ZU1vZGVsKHBhcnNlVHJlZSwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBzSW1wbCwgbnVsbCwgYXR0ck1vZGVsLCBiYXNlVHlwZSwgdHJ1ZSwgbnVsbCk7CgogICAgICAgIC8vIHN1bW1hcml6ZSB3aWxkY2FyZCBpbmZvcm1hdGlvbgogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjQXR0ciA9IHN1bW1hcml6ZUF0dHJXaWxkY2FyZHMoYXR0ck1vZGVsKTsKCiAgICAgICAgLy8gYWRkIGF0dHJpYnV0ZSBwcm9wZXJ0eSBtb2RlbAogICAgICAgIE1hcCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsID0gYnVpbGRBdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsQnlRTmFtZShhdHRyTW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gbm93IGZpbGwgaW4gdGhlIGFjdHVhbCBzY2hlbWEgdHlwZSBpbXBsZW1lbnRhdGlvbgogICAgICAgIHNJbXBsLnNldEJhc2VUeXBlUmVmKGJhc2VUeXBlLmdldFJlZigpKTsKICAgICAgICBzSW1wbC5zZXRCYXNlRGVwdGgoKChTY2hlbWFUeXBlSW1wbCliYXNlVHlwZSkuZ2V0QmFzZURlcHRoKCkgKyAxKTsKICAgICAgICBzSW1wbC5zZXREZXJpdmF0aW9uVHlwZShTY2hlbWFUeXBlLkRUX0VYVEVOU0lPTik7CiAgICAgICAgc0ltcGwuc2V0QW5vbnltb3VzVHlwZVJlZnMobWFrZVJlZkFycmF5KGFub255bW91c1R5cGVzKSk7CiAgICAgICAgc0ltcGwuc2V0V2lsZGNhcmRTdW1tYXJ5KFFOYW1lU2V0LkVNUFRZLCBmYWxzZSwgd2NBdHRyLnR5cGVkV2lsZGNhcmRzLCB3Y0F0dHIuaGFzV2lsZGNhcmRzKTsKICAgICAgICBzSW1wbC5zZXRDb21wbGV4VHlwZVZhcmlldHkoU2NoZW1hVHlwZS5TSU1QTEVfQ09OVEVOVCk7CiAgICAgICAgc0ltcGwuc2V0Q29udGVudE1vZGVsKG51bGwsIGF0dHJNb2RlbCwgbnVsbCwgYXR0cmlidXRlUHJvcGVydHlNb2RlbCwgZmFsc2UpOwogICAgICAgIHNJbXBsLnNldFNpbXBsZVR5cGVWYXJpZXR5KGJhc2VUeXBlLmdldFNpbXBsZVZhcmlldHkoKSk7CiAgICAgICAgc0ltcGwuc2V0UHJpbWl0aXZlVHlwZVJlZihiYXNlVHlwZS5nZXRQcmltaXRpdmVUeXBlKCkgPT0gbnVsbCA/IG51bGwgOiBiYXNlVHlwZS5nZXRQcmltaXRpdmVUeXBlKCkuZ2V0UmVmKCkpOwogICAgICAgIHN3aXRjaCAoc0ltcGwuZ2V0U2ltcGxlVmFyaWV0eSgpKQogICAgICAgIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLkxJU1Q6CiAgICAgICAgICAgICAgICBzSW1wbC5zZXRMaXN0SXRlbVR5cGVSZWYoYmFzZVR5cGUuZ2V0TGlzdEl0ZW1UeXBlKCkuZ2V0UmVmKCkpOwogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuVU5JT046CiAgICAgICAgICAgICAgICBzSW1wbC5zZXRVbmlvbk1lbWJlclR5cGVSZWZzKG1ha2VSZWZBcnJheShBcnJheXMuYXNMaXN0KGJhc2VUeXBlLmdldFVuaW9uTWVtYmVyVHlwZXMoKSkpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KCiAgICAgICAgLy8gZGVhbCB3aXRoIGZhY2V0cwogICAgICAgIFN0c2NTaW1wbGVUeXBlUmVzb2x2ZXIucmVzb2x2ZUZhY2V0cyhzSW1wbCwgbnVsbCwgKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKTsKCiAgICAgICAgLy8gbm93IGNvbXB1dGUgb3VyIGludHJpbnNpYyBwcm9wZXJ0aWVzCiAgICAgICAgU3RzY1NpbXBsZVR5cGVSZXNvbHZlci5yZXNvbHZlRnVuZGFtZW50YWxGYWNldHMoc0ltcGwpOwogICAgfQoKICAgIHN0YXRpYyBjbGFzcyBXaWxkY2FyZFJlc3VsdAogICAgewogICAgICAgIFdpbGRjYXJkUmVzdWx0KFFOYW1lU2V0IHR5cGVkV2lsZGNhcmRzLCBib29sZWFuIGhhc1dpbGRjYXJkcykKICAgICAgICB7CiAgICAgICAgICAgIHRoaXMudHlwZWRXaWxkY2FyZHMgPSB0eXBlZFdpbGRjYXJkczsKICAgICAgICAgICAgdGhpcy5oYXNXaWxkY2FyZHMgPSBoYXNXaWxkY2FyZHM7CiAgICAgICAgfQogICAgICAgIFFOYW1lU2V0IHR5cGVkV2lsZGNhcmRzOwogICAgICAgIGJvb2xlYW4gaGFzV2lsZGNhcmRzOwogICAgfQoKICAgIHN0YXRpYyBXaWxkY2FyZFJlc3VsdCBzdW1tYXJpemVBdHRyV2lsZGNhcmRzKFNjaGVtYUF0dHJpYnV0ZU1vZGVsIGF0dHJNb2RlbCkKICAgIHsKICAgICAgICBpZiAoYXR0ck1vZGVsLmdldFdpbGRjYXJkUHJvY2VzcygpID09IFNjaGVtYUF0dHJpYnV0ZU1vZGVsLk5PTkUpCiAgICAgICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoUU5hbWVTZXQuRU1QVFksIGZhbHNlKTsKICAgICAgICBpZiAoYXR0ck1vZGVsLmdldFdpbGRjYXJkUHJvY2VzcygpID09IFNjaGVtYUF0dHJpYnV0ZU1vZGVsLlNLSVApCiAgICAgICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoUU5hbWVTZXQuRU1QVFksIHRydWUpOwogICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoYXR0ck1vZGVsLmdldFdpbGRjYXJkU2V0KCksIHRydWUpOwogICAgfQoKICAgIHN0YXRpYyBXaWxkY2FyZFJlc3VsdCBzdW1tYXJpemVFbHRXaWxkY2FyZHMoU2NoZW1hUGFydGljbGUgY29udGVudE1vZGVsKQogICAgewogICAgICAgIGlmIChjb250ZW50TW9kZWwgPT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoUU5hbWVTZXQuRU1QVFksIGZhbHNlKTsKICAgICAgICB9CgogICAgICAgIHN3aXRjaCAoY29udGVudE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpKQogICAgICAgIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQ0hPSUNFOgogICAgICAgICAgICAgICAgUU5hbWVTZXRCdWlsZGVyIHNldCA9IG5ldyBRTmFtZVNldEJ1aWxkZXIoKTsKICAgICAgICAgICAgICAgIGJvb2xlYW4gaGFzV2lsZGNhcmRzID0gZmFsc2U7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNvbnRlbnRNb2RlbC5jb3VudE9mUGFydGljbGVDaGlsZCgpOyBpKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgV2lsZGNhcmRSZXN1bHQgaW5uZXIgPSBzdW1tYXJpemVFbHRXaWxkY2FyZHMoY29udGVudE1vZGVsLmdldFBhcnRpY2xlQ2hpbGQoaSkpOwogICAgICAgICAgICAgICAgICAgIHNldC5hZGRBbGwoaW5uZXIudHlwZWRXaWxkY2FyZHMpOwogICAgICAgICAgICAgICAgICAgIGhhc1dpbGRjYXJkcyB8PSBpbm5lci5oYXNXaWxkY2FyZHM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFdpbGRjYXJkUmVzdWx0KHNldC50b1FOYW1lU2V0KCksIGhhc1dpbGRjYXJkcyk7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFdpbGRjYXJkUmVzdWx0KAogICAgICAgICAgICAgICAgICAgIChjb250ZW50TW9kZWwuZ2V0V2lsZGNhcmRQcm9jZXNzKCkgPT0gU2NoZW1hUGFydGljbGUuU0tJUCkgPwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0LkVNUFRZIDogY29udGVudE1vZGVsLmdldFdpbGRjYXJkU2V0KCksIHRydWUpOwogICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGZhbGx0aHJvdWdoCgogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBXaWxkY2FyZFJlc3VsdChRTmFtZVNldC5FTVBUWSwgZmFsc2UpOwogICAgICAgIH0KICAgIH0KCiAgICBzdGF0aWMgdm9pZCB0cmFuc2xhdGVBdHRyaWJ1dGVNb2RlbCgKICAgICAgICAgICAgWG1sT2JqZWN0IHBhcnNlVHJlZSwgU3RyaW5nIHRhcmdldE5hbWVzcGFjZSwgYm9vbGVhbiBjaGFtZWxlb24sCiAgICAgICAgICAgIExpc3QgYW5vbnltb3VzVHlwZXMsIFNjaGVtYVR5cGUgb3V0ZXJUeXBlLAogICAgICAgICAgICBTZXQgc2VlbkF0dHJpYnV0ZXMsIFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCByZXN1bHQsIFNjaGVtYVR5cGUgYmFzZVR5cGUsIGJvb2xlYW4gZXh0ZW5zaW9uLCBRTmFtZSByZWRlZmluaXRpb25Gb3IpCiAgICB7CiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwogICAgICAgIGlmIChzZWVuQXR0cmlidXRlcyA9PSBudWxsKQogICAgICAgICAgICBzZWVuQXR0cmlidXRlcyA9IG5ldyBIYXNoU2V0KCk7CiAgICAgICAgYm9vbGVhbiBzZWVuV2lsZGNhcmQgPSBmYWxzZTsKICAgICAgICBib29sZWFuIHNlZW5SZWRlZmluaXRpb24gPSBmYWxzZTsKICAgICAgICBTY2hlbWFBdHRyaWJ1dGVNb2RlbCBiYXNlTW9kZWwgPSBudWxsOwogICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsKQogICAgICAgICAgICBiYXNlTW9kZWwgPSBiYXNlVHlwZS5nZXRBdHRyaWJ1dGVNb2RlbCgpOwoKICAgICAgICBYbWxDdXJzb3IgY3VyID0gcGFyc2VUcmVlLm5ld0N1cnNvcigpOwoKICAgICAgICBmb3IgKGJvb2xlYW4gbW9yZSA9IGN1ci50b0ZpcnN0Q2hpbGQoKTsgbW9yZTsgbW9yZSA9IGN1ci50b05leHRTaWJsaW5nKCkpCiAgICAgICAgewogICAgICAgICAgICBzd2l0Y2ggKHRyYW5zbGF0ZUF0dHJpYnV0ZUNvZGUoY3VyLmdldE5hbWUoKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNhc2UgQVRUUklCVVRFX0NPREU6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgQXR0cmlidXRlIHhzZGF0dHIgPSAoQXR0cmlidXRlKWN1ci5nZXRPYmplY3QoKTsKCiAgICAgICAgICAgICAgICAgICAgU2NoZW1hTG9jYWxBdHRyaWJ1dGUgc0F0dHIgPSBTdHNjVHJhbnNsYXRvci50cmFuc2xhdGVBdHRyaWJ1dGUoeHNkYXR0ciwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBvdXRlclR5cGUsIGJhc2VNb2RlbCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHNBdHRyID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwoKICAgICAgICAgICAgICAgICAgICBpZiAoc2VlbkF0dHJpYnV0ZXMuY29udGFpbnMoc0F0dHIuZ2V0TmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBdHRyaWJ1dGUgd2l0aCB0aGUgc2FtZSBuYW1lIGFscmVhZHkgZGVmaW5lZCAiLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FUVFJJQlVURV9OQU1FLCB4c2RhdHRyLnhnZXROYW1lKCkpOwogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gaWdub3JlIHRoZSBkdXBsaWNhdGUgYXR0cgogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgc2VlbkF0dHJpYnV0ZXMuYWRkKHNBdHRyLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaWYgKGJhc2VNb2RlbCAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgU2NoZW1hTG9jYWxBdHRyaWJ1dGUgYmFzZUF0dHIgPSBiYXNlTW9kZWwuZ2V0QXR0cmlidXRlKHNBdHRyLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXNlQXR0ciA9PSBudWxsKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV4dGVuc2lvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWJhc2VNb2RlbC5nZXRXaWxkY2FyZFNldCgpLmNvbnRhaW5zKHNBdHRyLmdldE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHJlc3RyaWN0aW9uIGNhbm5vdCBpbnRyb2R1Y2UgYSBuZXcgYXR0cmlidXRlIHRoYXQgd291bGQgbm90IGJlIGFsbG93ZWQgaW4gdGhlIGJhc2UgdHlwZS4iLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FUVFJJQlVURV9OQU1FLCB4c2RhdHRyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChleHRlbnNpb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNBdHRyLmdldFVzZSgpID09IFNjaGVtYUxvY2FsQXR0cmlidXRlLlBST0hJQklURUQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBbiBleHRlbnNpb24gY2Fubm90IHByb2hpYml0IGFuIGF0dHJpYnV0ZSBmcm9tIHRoZSBiYXNlIHR5cGU7IHVzZSByZXN0cmljdGlvbiBpbnN0ZWFkLiIsIFhtbEVycm9yQ29udGV4dC5EVVBMSUNBVEVfQVRUUklCVVRFX05BTUUsIHhzZGF0dHIueGdldFVzZSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc0F0dHIuZ2V0VXNlKCkgIT0gU2NoZW1hTG9jYWxBdHRyaWJ1dGUuUkVRVUlSRUQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZUF0dHIuZ2V0VXNlKCkgPT0gU2NoZW1hTG9jYWxBdHRyaWJ1dGUuUkVRVUlSRUQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSByZXN0cmljdGlvbiBjYW5ub3QgbW9kaWZ5IGFuIGF0dHJpYnV0ZSB0aGF0IGlzIHJlcXVpcmVkIGluIHRoZSBiYXNlIHR5cGUgdG8gYmUgcHJvaGliaXRlZCBvciBvcHRpb25hbC4iLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FUVFJJQlVURV9OQU1FLCB4c2RhdHRyLnhnZXRVc2UoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc0F0dHIuZ2V0VXNlKCkgPT0gU2NoZW1hTG9jYWxBdHRyaWJ1dGUuUFJPSElCSVRFRCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5yZW1vdmVQcm9oaWJpdGVkQXR0cmlidXRlKHNBdHRyLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBpZiAoc0F0dHIuZ2V0VXNlKCkgIT0gU2NoZW1hTG9jYWxBdHRyaWJ1dGUuUFJPSElCSVRFRCkKICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFkZEF0dHJpYnV0ZShzQXR0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmIChzQXR0ci5nZXREZWZhdWx0VGV4dCgpICE9IG51bGwgJiYgIXNBdHRyLmlzRml4ZWQoKSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzQXR0ci5nZXRVc2UoKSAhPSBTY2hlbWFMb2NhbEF0dHJpYnV0ZS5PUFRJT05BTCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBbiBhdHRyaWJ1dGUgZGVjbGFyYXRpb24gbXVzdCBiZSBvcHRpb25hbCBpbiBvcmRlciB0byBzcGVjaWZ5IGEgZGVmYXVsdCIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCB4c2RhdHRyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIAoKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNhc2UgQU5ZX0FUVFJJQlVURV9DT0RFOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFdpbGRjYXJkIHhzZHdjID0gKFdpbGRjYXJkKWN1ci5nZXRPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgICBpZiAoc2VlbldpbGRjYXJkKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk9ubHkgb25lIGF0dHJpYnV0ZSB3aWxkY2FyZCBhbGxvd2VkIiwgWG1sRXJyb3JDb250ZXh0LkRVUExJQ0FURV9BTllfQVRUUklCVVRFLCB4c2R3Yyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBpZ25vcmUgdGhlIGV4dHJhIHdpbGRjYXJkCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNlZW5XaWxkY2FyZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgTmFtZXNwYWNlTGlzdCBuc0xpc3QgPSB4c2R3Yy54Z2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgICAgICAgICAgU3RyaW5nIG5zVGV4dDsKICAgICAgICAgICAgICAgICAgICBpZiAobnNMaXN0ID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgIG5zVGV4dCA9ICIjI2FueSI7CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICBuc1RleHQgPSBuc0xpc3QuZ2V0U3RyaW5nVmFsdWUoKTsKICAgICAgICAgICAgICAgICAgICBRTmFtZVNldCB3Y3NldCA9IFFOYW1lU2V0LmZvcldpbGRjYXJkTmFtZXNwYWNlU3RyaW5nKG5zVGV4dCwgdGFyZ2V0TmFtZXNwYWNlKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZU1vZGVsICE9IG51bGwgJiYgIWV4dGVuc2lvbikKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXNlTW9kZWwuZ2V0V2lsZGNhcmRTZXQoKSA9PSBudWxsKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSByZXN0cmljdGlvbiBjYW5ub3QgYWRkIGFueUF0dHJpYnV0ZSB3aGVuIHRoZSBiYXNlIHR5cGUgZG9lcyBub3QgaGF2ZSBhbnlBdHRyaWJ1dGUiLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FOWV9BVFRSSUJVVEUsIHhzZHdjKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBpZ25vcmUgdGhlIGV4dHJhIHdpbGRjYXJkCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWJhc2VNb2RlbC5nZXRXaWxkY2FyZFNldCgpLmNvbnRhaW5zQWxsKHdjc2V0KSkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlRoZSBhbnlBdHRyaWJ1dGUgbmFtZXNwYWNlPSciICsgbnNUZXh0ICsgIicgaXMgbm90IGEgc3Vic2V0IG9mIHRoZSBiYXNlIHR5cGUgYW55QXR0cmlidXRlIiwgWG1sRXJyb3JDb250ZXh0LkRVUExJQ0FURV9BTllfQVRUUklCVVRFLCB4c2R3Yyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gaWdub3JlIHRoZSByZXN0cmljdGlvbgogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGludCB3Y3Byb2Nlc3MgPSB0cmFuc2xhdGVXaWxkY2FyZFByb2Nlc3MoeHNkd2MueGdldFByb2Nlc3NDb250ZW50cygpKTsKICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmdldFdpbGRjYXJkUHJvY2VzcygpID09IFNjaGVtYUF0dHJpYnV0ZU1vZGVsLk5PTkUpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuc2V0V2lsZGNhcmRTZXQod2NzZXQpOwogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuc2V0V2lsZGNhcmRQcm9jZXNzKHdjcHJvY2Vzcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChleHRlbnNpb24pCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5zZXRXaWxkY2FyZFNldCh3Y3NldC51bmlvbihyZXN1bHQuZ2V0V2lsZGNhcmRTZXQoKSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNldFdpbGRjYXJkUHJvY2Vzcyh3Y3Byb2Nlc3MpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNldFdpbGRjYXJkU2V0KHdjc2V0LmludGVyc2VjdChyZXN1bHQuZ2V0V2lsZGNhcmRTZXQoKSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBvbGQgcHJvY2VzcwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2FzZSBBVFRSSUJVVEVfR1JPVVBfQ09ERToKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBBdHRyaWJ1dGVHcm91cFJlZiB4c2RhZyA9IChBdHRyaWJ1dGVHcm91cFJlZiljdXIuZ2V0T2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgUU5hbWUgcmVmID0geHNkYWcuZ2V0UmVmKCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlZiA9PSBudWxsKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkF0dHJpYnV0ZSBncm91cCByZWZlcmVuY2UgbXVzdCBoYXZlIGEgcmVmIGF0dHJpYnV0ZSIsIFhtbEVycm9yQ29udGV4dC5BVFRSSUJVVEVfR1JPVVBfTUlTU0lOR19SRUYsIHhzZGFnKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIFNjaGVtYUF0dHJpYnV0ZUdyb3VwSW1wbCBncm91cDsKICAgICAgICAgICAgICAgICAgICBpZiAocmVkZWZpbml0aW9uRm9yICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IHN0YXRlLmZpbmRSZWRlZmluZWRBdHRyaWJ1dGVHcm91cChyZWYsIGNoYW1lbGVvbiA/IHRhcmdldE5hbWVzcGFjZSA6IG51bGwsIHJlZGVmaW5pdGlvbkZvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChncm91cCAhPSBudWxsICYmIHJlZGVmaW5pdGlvbkZvci5lcXVhbHMoZ3JvdXAuZ2V0TmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlZW5SZWRlZmluaXRpb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkFuIGF0dHJpYnV0ZSBncm91cCByZWRlZmluaXRpb24gbXVzdCBpbmNsdWRlIGF0IG1vc3Qgb25lIHJlZmVyZW5jZSB0byB0aGUgb3JpZ2luYWwgZGVmaW5pdGlvbi4iLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgeHNkYWcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlblJlZGVmaW5pdGlvbiA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBzdGF0ZS5maW5kQXR0cmlidXRlR3JvdXAocmVmLCBjaGFtZWxlb24gPyB0YXJnZXROYW1lc3BhY2UgOiBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5ub3RGb3VuZEVycm9yKHJlZiwgWG1sRXJyb3JDb250ZXh0LkFUVFJJQlVURV9HUk9VUF9OT1RfRk9VTkQsIHhzZGFnLnhnZXRSZWYoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUuaXNQcm9jZXNzaW5nKGdyb3VwKSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBdHRyaWJ1dGUgZ3JvdXAgIiArIFFOYW1lSGVscGVyLnByZXR0eShncm91cC5nZXROYW1lKCkpICsgIiByZWZlcmVuY2VzIGl0c2VsZiIsIFhtbEVycm9yQ29udGV4dC5DWUNMSUNfREVQRU5ERU5DWSwgZ3JvdXAuZ2V0UGFyc2VPYmplY3QoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBTdHJpbmcgc3ViVGFyZ2V0TmFtZXNwYWNlID0gdGFyZ2V0TmFtZXNwYWNlOwogICAgICAgICAgICAgICAgICAgIGlmIChncm91cC5nZXRUYXJnZXROYW1lc3BhY2UoKSAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3ViVGFyZ2V0TmFtZXNwYWNlID0gZ3JvdXAuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW1lbGVvbiA9IGdyb3VwLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpICE9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zdGFydFByb2Nlc3NpbmcoZ3JvdXApOwogICAgICAgICAgICAgICAgICAgIFFOYW1lIG5lc3RlZFJlZGVmaW5pdGlvbkZvciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLmlzUmVkZWZpbml0aW9uKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIG5lc3RlZFJlZGVmaW5pdGlvbkZvciA9IGdyb3VwLmdldE5hbWUoKTsKICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVBdHRyaWJ1dGVNb2RlbChncm91cC5nZXRQYXJzZU9iamVjdCgpLCBzdWJUYXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIG91dGVyVHlwZSwgc2VlbkF0dHJpYnV0ZXMsIHJlc3VsdCwgYmFzZVR5cGUsIGV4dGVuc2lvbiwgbmVzdGVkUmVkZWZpbml0aW9uRm9yKTsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5maW5pc2hQcm9jZXNzaW5nKGdyb3VwKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7IC8vIHNraXAgdGhpbmdzIHRoYXQgYXJlIG5vdCBwYXJ0IG9mIHRoZSBhdHRyaWJ1dGUgbW9kZWwuCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgc3RhdGljIFNjaGVtYVBhcnRpY2xlIGV4dGVuZENvbnRlbnRNb2RlbChTY2hlbWFQYXJ0aWNsZSBiYXNlQ29udGVudE1vZGVsLCBTY2hlbWFQYXJ0aWNsZSBleHRlbmRlZENvbnRlbnRNb2RlbCwgWG1sT2JqZWN0IHBhcnNlVHJlZSkKICAgIHsKICAgICAgICAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi94bWxzY2hlbWEtMS8jZWxlbWVudC1jb21wbGV4Q29udGVudDo6ZXh0ZW5zaW9uCiAgICAgICAgCiAgICAgICAgLy8gMi4xIElmIHRoZSC3ZXhwbGljaXQgY29udGVudLcgaXMgZW1wdHksIHRoZW4gdGhlIHtjb250ZW50IHR5cGV9IG9mIHRoZSB0eXBlIGRlZmluaXRpb24gt3Jlc29sdmVktyB0byBieSB0aGUgt2FjdHVhbCB2YWx1Zbcgb2YgdGhlIGJhc2UgW2F0dHJpYnV0ZV0gCiAgICAgICAgaWYgKGV4dGVuZGVkQ29udGVudE1vZGVsID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBiYXNlQ29udGVudE1vZGVsOwogICAgICAgIAogICAgICAgIC8vIDIuMiBJZiB0aGUgdHlwZSBkZWZpbml0aW9uILdyZXNvbHZlZLcgdG8gYnkgdGhlILdhY3R1YWwgdmFsdWW3IG9mIHRoZSBiYXNlIFthdHRyaWJ1dGVdIGhhcyBhIHtjb250ZW50IHR5cGV9IG9mIGVtcHR5LCB0aGVuIGEgcGFpciBvZiBtaXhlZCBvciBlbGVtZW50T25seSAoZGV0ZXJtaW5lZCBhcyBwZXIgY2xhdXNlIDEuMi4xIGFib3ZlKSBhbmQgdGhlILdleHBsaWNpdCBjb250ZW50tyBpdHNlbGY7CiAgICAgICAgaWYgKGJhc2VDb250ZW50TW9kZWwgPT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIGV4dGVuZGVkQ29udGVudE1vZGVsOwogICAgICAgIAogICAgICAgIC8vIDIuMyBvdGhlcndpc2UgYSBwYWlyIG9mIG1peGVkIG9yIGVsZW1lbnRPbmx5IChkZXRlcm1pbmVkIGFzIHBlciBjbGF1c2UgMS4yLjEgYWJvdmUpIGFuZCBhIHBhcnRpY2xlIHdob3NlIHByb3BlcnRpZXMgYXJlIGFzIGZvbGxvd3M6ICAKICAgICAgICBTY2hlbWFQYXJ0aWNsZUltcGwgc1BhcnQgPSBuZXcgU2NoZW1hUGFydGljbGVJbXBsKCk7CiAgICAgICAgc1BhcnQuc2V0UGFydGljbGVUeXBlKFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFKTsKCiAgICAgICAgTGlzdCBhY2N1bXVsYXRlID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIGFkZE1pbnVzUG9pbnRsZXNzUGFydGljbGVzKGFjY3VtdWxhdGUsIGJhc2VDb250ZW50TW9kZWwsIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFKTsKICAgICAgICBhZGRNaW51c1BvaW50bGVzc1BhcnRpY2xlcyhhY2N1bXVsYXRlLCBleHRlbmRlZENvbnRlbnRNb2RlbCwgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0UpOwogICAgICAgIHNQYXJ0LnNldE1pbk9jY3VycyhCaWdJbnRlZ2VyLk9ORSk7CiAgICAgICAgc1BhcnQuc2V0TWF4T2NjdXJzKEJpZ0ludGVnZXIuT05FKTsKICAgICAgICBzUGFydC5zZXRQYXJ0aWNsZUNoaWxkcmVuKChTY2hlbWFQYXJ0aWNsZVtdKQogICAgICAgICAgICAgICAgYWNjdW11bGF0ZS50b0FycmF5KG5ldyBTY2hlbWFQYXJ0aWNsZVthY2N1bXVsYXRlLnNpemUoKV0pKTsKCiAgICAgICAgcmV0dXJuIGZpbHRlclBvaW50bGVzc1BhcnRpY2xlc0FuZFZlcmlmeUFsbFBhcnRpY2xlcyhzUGFydCwgcGFyc2VUcmVlKTsKICAgIH0KCiAgICBzdGF0aWMgQmlnSW50ZWdlciBleHRyYWN0TWluT2NjdXJzKFhtbE5vbk5lZ2F0aXZlSW50ZWdlciBubmkpCiAgICB7CiAgICAgICAgaWYgKG5uaSA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gQmlnSW50ZWdlci5PTkU7CiAgICAgICAgQmlnSW50ZWdlciByZXN1bHQgPSBubmkuZ2V0QmlnSW50ZWdlclZhbHVlKCk7CiAgICAgICAgaWYgKHJlc3VsdCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gQmlnSW50ZWdlci5PTkU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICBzdGF0aWMgQmlnSW50ZWdlciBleHRyYWN0TWF4T2NjdXJzKEFsbE5OSSBhbGxOTkkpCiAgICB7CiAgICAgICAgaWYgKGFsbE5OSSA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gQmlnSW50ZWdlci5PTkU7CgogICAgICAgIGlmIChhbGxOTkkuaW5zdGFuY2VUeXBlKCkuZ2V0UHJpbWl0aXZlVHlwZSgpLmdldEJ1aWx0aW5UeXBlQ29kZSgpID09IFNjaGVtYVR5cGUuQlRDX0RFQ0lNQUwpCiAgICAgICAgICAgIHJldHVybiAoKFhtbEludGVnZXIpYWxsTk5JKS5nZXRCaWdJbnRlZ2VyVmFsdWUoKTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgCiAgICBwcml2YXRlIHN0YXRpYyBjbGFzcyBSZWRlZmluaXRpb25Gb3JHcm91cAogICAgewogICAgICAgIHByaXZhdGUgUU5hbWUgZ3JvdXBOYW1lOwogICAgICAgIHByaXZhdGUgYm9vbGVhbiBzZWVuUmVkZWZpbml0aW9uID0gZmFsc2U7CgogICAgICAgIHB1YmxpYyBSZWRlZmluaXRpb25Gb3JHcm91cChRTmFtZSBncm91cE5hbWUpCiAgICAgICAgewogICAgICAgICAgICB0aGlzLmdyb3VwTmFtZSA9IGdyb3VwTmFtZTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBRTmFtZSBnZXRHcm91cE5hbWUoKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIGdyb3VwTmFtZTsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBib29sZWFuIGlzU2VlblJlZGVmaW5pdGlvbigpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gc2VlblJlZGVmaW5pdGlvbjsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyB2b2lkIHNldFNlZW5SZWRlZmluaXRpb24oYm9vbGVhbiBzZWVuUmVkZWZpbml0aW9uKQogICAgICAgIHsKICAgICAgICAgICAgdGhpcy5zZWVuUmVkZWZpbml0aW9uID0gc2VlblJlZGVmaW5pdGlvbjsKICAgICAgICB9CiAgICB9CgogICAgc3RhdGljIFNjaGVtYVBhcnRpY2xlIHRyYW5zbGF0ZUNvbnRlbnRNb2RlbCgKICAgICAgICAgICAgU2NoZW1hVHlwZSBvdXRlclR5cGUsCiAgICAgICAgICAgIFhtbE9iamVjdCBwYXJzZVRyZWUsIFN0cmluZyB0YXJnZXROYW1lc3BhY2UsIGJvb2xlYW4gY2hhbWVsZW9uLAogICAgICAgICAgICBpbnQgcGFydGljbGVDb2RlLAogICAgICAgICAgICBMaXN0IGFub255bW91c1R5cGVzLCBNYXAgZWxlbWVudE1vZGVsLAogICAgICAgICAgICBib29sZWFuIGFsbG93RWx0LCBSZWRlZmluaXRpb25Gb3JHcm91cCByZWRlZmluaXRpb25Gb3IpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlVHJlZSA9PSBudWxsIHx8IHBhcnRpY2xlQ29kZSA9PSAwKQogICAgICAgICAgICByZXR1cm4gbnVsbDsKCiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwoKICAgICAgICAvLyBlbWl0REJHKCJUcmFuc2xhdGluZyBjb250ZW50IG1vZGVsIGZvciAiICsgb3V0ZXJUeXBlKTsKICAgICAgICAvLyBpbmRlbnREQkcoKTsKICAgICAgICBpZiAoWG1sQmVhbnMuQVNTRVJUUykKICAgICAgICAgICAgWG1sQmVhbnMuYXNzZXJ0VHJ1ZShwYXJ0aWNsZUNvZGUgIT0gMCk7CgogICAgICAgIGJvb2xlYW4gaGFzQ2hpbGRyZW4gPSBmYWxzZTsKICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VyczsKICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3VyczsKICAgICAgICBTY2hlbWFNb2RlbEdyb3VwSW1wbCBncm91cCA9IG51bGw7CgogICAgICAgIFNjaGVtYVBhcnRpY2xlSW1wbCBzUGFydDsKCiAgICAgICAgaWYgKHBhcnRpY2xlQ29kZSA9PSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCFhbGxvd0VsdCkKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNdXN0IGJlIGEgc2VxdWVuY2UsIGNob2ljZSBvciBhbGwgaGVyZSIsIFhtbEVycm9yQ29udGV4dC5FWFBMSUNJVF9HUk9VUF9ORUVERUQsIHBhcnNlVHJlZSk7CgogICAgICAgICAgICAvLyBUT0RPOiBkZXRlY3Qgc3Vic3RpdHV0aW9uIGdyb3VwIGZvciB0aGlzIGVsZW1lbnQgYW5kIGNvbnN0cnVjdCBhIGNob2ljZQoKICAgICAgICAgICAgTG9jYWxFbGVtZW50IHBhcnNlRWx0ID0gKExvY2FsRWxlbWVudClwYXJzZVRyZWU7CiAgICAgICAgICAgIHNQYXJ0ID0gU3RzY1RyYW5zbGF0b3IudHJhbnNsYXRlRWxlbWVudChwYXJzZUVsdCwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBvdXRlclR5cGUpOwogICAgICAgICAgICBpZiAoc1BhcnQgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICBtaW5PY2N1cnMgPSBleHRyYWN0TWluT2NjdXJzKHBhcnNlRWx0LnhnZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgICAgIG1heE9jY3VycyA9IGV4dHJhY3RNYXhPY2N1cnMocGFyc2VFbHQueGdldE1heE9jY3VycygpKTsKCiAgICAgICAgICAgIFNjaGVtYVR5cGUgb2xkVHlwZSA9IChTY2hlbWFUeXBlKWVsZW1lbnRNb2RlbC5nZXQoc1BhcnQuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgaWYgKG9sZFR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZWxlbWVudE1vZGVsLnB1dChzUGFydC5nZXROYW1lKCksIHNQYXJ0LmdldFR5cGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoIXNQYXJ0LmdldFR5cGUoKS5lcXVhbHMob2xkVHlwZSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJUeXBlIG9mICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoc1BhcnQuZ2V0TmFtZSgpKSArICIgaXMgaW5jb25zaXN0ZW50IHdpdGggYW5vdGhlciBlbGVtZW50IHdpdGggdGhlIHNhbWUgbmFtZSBpbiB0aGlzIGNvbnRlbnQgbW9kZWwiLCBYbWxFcnJvckNvbnRleHQuSU5DT05TSVNURU5UX1RZUEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChwYXJ0aWNsZUNvZGUgPT0gU2NoZW1hUGFydGljbGUuV0lMRENBUkQpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWFsbG93RWx0KQogICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk11c3QgYmUgYSBzZXF1ZW5jZSwgY2hvaWNlIG9yIGFsbCBoZXJlIiwgWG1sRXJyb3JDb250ZXh0LkVYUExJQ0lUX0dST1VQX05FRURFRCwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgQW55IHBhcnNlQW55ID0gKEFueSlwYXJzZVRyZWU7CiAgICAgICAgICAgIHNQYXJ0ID0gbmV3IFNjaGVtYVBhcnRpY2xlSW1wbCgpOwogICAgICAgICAgICBzUGFydC5zZXRQYXJ0aWNsZVR5cGUoU2NoZW1hUGFydGljbGUuV0lMRENBUkQpOwogICAgICAgICAgICBRTmFtZVNldCB3Y3NldDsKICAgICAgICAgICAgTmFtZXNwYWNlTGlzdCBuc2xpc3QgPSBwYXJzZUFueS54Z2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgIGlmIChuc2xpc3QgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHdjc2V0ID0gUU5hbWVTZXQuQUxMOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB3Y3NldCA9IFFOYW1lU2V0LmZvcldpbGRjYXJkTmFtZXNwYWNlU3RyaW5nKG5zbGlzdC5nZXRTdHJpbmdWYWx1ZSgpLCB0YXJnZXROYW1lc3BhY2UpOwogICAgICAgICAgICBzUGFydC5zZXRXaWxkY2FyZFNldCh3Y3NldCk7CiAgICAgICAgICAgIHNQYXJ0LnNldFdpbGRjYXJkUHJvY2Vzcyh0cmFuc2xhdGVXaWxkY2FyZFByb2Nlc3MocGFyc2VBbnkueGdldFByb2Nlc3NDb250ZW50cygpKSk7CiAgICAgICAgICAgIG1pbk9jY3VycyA9IGV4dHJhY3RNaW5PY2N1cnMocGFyc2VBbnkueGdldE1pbk9jY3VycygpKTsKICAgICAgICAgICAgbWF4T2NjdXJzID0gZXh0cmFjdE1heE9jY3VycyhwYXJzZUFueS54Z2V0TWF4T2NjdXJzKCkpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBHcm91cCBwYXJzZUdyb3VwID0gKEdyb3VwKXBhcnNlVHJlZTsKICAgICAgICAgICAgc1BhcnQgPSBuZXcgU2NoZW1hUGFydGljbGVJbXBsKCk7CgogICAgICAgICAgICAvLyBncmFiIG1pbi9tYXhPY2N1cnMgYmVmb3JlIGRlcmVmZXJlbmNpZ24gZ3JvdXAgcmVmCiAgICAgICAgICAgIG1pbk9jY3VycyA9IGV4dHJhY3RNaW5PY2N1cnMocGFyc2VHcm91cC54Z2V0TWluT2NjdXJzKCkpOwogICAgICAgICAgICBtYXhPY2N1cnMgPSBleHRyYWN0TWF4T2NjdXJzKHBhcnNlR3JvdXAueGdldE1heE9jY3VycygpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgPT0gTU9ERUxfR1JPVVBfQ09ERSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgUU5hbWUgcmVmID0gcGFyc2VHcm91cC5nZXRSZWYoKTsKICAgICAgICAgICAgICAgIGlmIChyZWYgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiR3JvdXAgcmVmZXJlbmNlIG11c3QgaGF2ZSBhIHJlZiBhdHRyaWJ1dGUiLCBYbWxFcnJvckNvbnRleHQuR1JPVVBfTUlTU0lOR19SRUYsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmIChyZWRlZmluaXRpb25Gb3IgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBncm91cCA9IHN0YXRlLmZpbmRSZWRlZmluZWRNb2RlbEdyb3VwKHJlZiwgY2hhbWVsZW9uID8gdGFyZ2V0TmFtZXNwYWNlIDogbnVsbCwgcmVkZWZpbml0aW9uRm9yLmdldEdyb3VwTmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZ3JvdXAgIT0gbnVsbCAmJiBncm91cC5nZXROYW1lKCkuZXF1YWxzKHJlZGVmaW5pdGlvbkZvci5nZXRHcm91cE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVkZWZpbml0aW9uRm9yLmlzU2VlblJlZGVmaW5pdGlvbigpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkdyb3VwIHJlZGVmaW5pdGlvbiBtdXN0IHJlZmVyIHRvIHRoZSBvcmlnaW5hbCBkZWZpbml0aW9uIGF0IG1vc3Qgb25jZSIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUJpZ0ludGVnZXIuT05FLmVxdWFscyhtYXhPY2N1cnMpIHx8ICFCaWdJbnRlZ2VyLk9ORS5lcXVhbHMobWluT2NjdXJzKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJXaGVuIHJlZmVyZW5jaW5nIHRoZSBvcmlnaW5hbCBncm91cCBkZWZpbml0aW9uIGluIGEgcmVkZWZpbml0aW9uLCBtYXhPY2N1cnMgYW5kIG1pbk9jY3VycyBtdXN0IGJlIDEiLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmVkZWZpbml0aW9uRm9yLnNldFNlZW5SZWRlZmluaXRpb24odHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGdyb3VwID0gc3RhdGUuZmluZE1vZGVsR3JvdXAocmVmLCBjaGFtZWxlb24gPyB0YXJnZXROYW1lc3BhY2UgOiBudWxsKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChncm91cCA9PSBudWxsKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocmVmLCBYbWxFcnJvckNvbnRleHQuTU9ERUxfR1JPVVBfTk9UX0ZPVU5ELCAoKEdyb3VwKXBhcnNlVHJlZSkueGdldFJlZigpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5pc1Byb2Nlc3NpbmcoZ3JvdXApKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNb2RlbCBncm91cCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGdyb3VwLmdldE5hbWUoKSkgKyAiIHJlZmVyZW5jZXMgaXRzZWxmIiwgWG1sRXJyb3JDb250ZXh0LkNZQ0xJQ19ERVBFTkRFTkNZLCBncm91cC5nZXRQYXJzZU9iamVjdCgpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgLy8gbm8gZ28gdG8gdGhlIGNoaWxkLgogICAgICAgICAgICAgICAgWG1sQ3Vyc29yIGN1ciA9IGdyb3VwLmdldFBhcnNlT2JqZWN0KCkubmV3Q3Vyc29yKCk7CiAgICAgICAgICAgICAgICBmb3IgKGJvb2xlYW4gbW9yZSA9IGN1ci50b0ZpcnN0Q2hpbGQoKTsgbW9yZTsgbW9yZSA9IGN1ci50b05leHRTaWJsaW5nKCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcGFydGljbGVDb2RlID0gdHJhbnNsYXRlUGFydGljbGVDb2RlKGN1ci5nZXROYW1lKCkpOwogICAgICAgICAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgIT0gMCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlVHJlZSA9IHBhcnNlR3JvdXAgPSAoR3JvdXApY3VyLmdldE9iamVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAocGFydGljbGVDb2RlID09IDApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk1vZGVsIGdyb3VwICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoZ3JvdXAuZ2V0TmFtZSgpKSArICIgaXMgZW1wdHkiLCBYbWxFcnJvckNvbnRleHQuRVhQTElDSVRfR1JPVVBfTkVFREVELCBncm91cC5nZXRQYXJzZU9iamVjdCgpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgIT0gU2NoZW1hUGFydGljbGUuQUxMICYmIHBhcnRpY2xlQ29kZSAhPSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRSAmJiBwYXJ0aWNsZUNvZGUgIT0gU2NoZW1hUGFydGljbGUuQ0hPSUNFKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNb2RlbCBncm91cCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGdyb3VwLmdldE5hbWUoKSkgKyAiIGlzIG5vdCBhIHNlcXVlbmNlLCBhbGwsIG9yIGNob2ljZSIsIFhtbEVycm9yQ29udGV4dC5FWFBMSUNJVF9HUk9VUF9ORUVERUQsIGdyb3VwLmdldFBhcnNlT2JqZWN0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBTdHJpbmcgbmV3VGFyZ2V0TmFtZXNwYWNlID0gZ3JvdXAuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgICAgICBpZiAobmV3VGFyZ2V0TmFtZXNwYWNlICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZXNwYWNlID0gbmV3VGFyZ2V0TmFtZXNwYWNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzd2l0Y2ggKHBhcnRpY2xlQ29kZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgc1BhcnQuc2V0UGFydGljbGVUeXBlKHBhcnRpY2xlQ29kZSk7CiAgICAgICAgICAgICAgICAgICAgaGFzQ2hpbGRyZW4gPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgaWYgKFhtbEJlYW5zLkFTU0VSVFMpCiAgICAgICAgICAgICAgICAgICAgICAgIFhtbEJlYW5zLmFzc2VydFRydWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKG1heE9jY3VycyAhPSBudWxsICYmIG1pbk9jY3Vycy5jb21wYXJlVG8obWF4T2NjdXJzKSA+IDApCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigibWF4T2NjdXJzIG11c3Qgbm90IGJlIGxlc3MgdGhhbiBtaW5PY2N1cnMiLCBYbWxFcnJvckNvbnRleHQuTUlOX01BWF9PQ0NVUlMsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIG1heE9jY3VycyA9IG1pbk9jY3VyczsgLy8gcmVtZWR5OiBwaW4gbWF4IHVwIHRvIG1pbgogICAgICAgIH0KCiAgICAgICAgaWYgKG1heE9jY3VycyAhPSBudWxsICYmIG1heE9jY3Vycy5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpIDwgMCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBudWxsOyAvLyBtYXhPY2N1cnMgPT0gbWluT2NjdXJzID09IDAsIHNhbWUgYXMgbm8gcGFydGljbGUgYXQgYWxsLgogICAgICAgIH0KCiAgICAgICAgc1BhcnQuc2V0TWluT2NjdXJzKG1pbk9jY3Vycyk7CiAgICAgICAgc1BhcnQuc2V0TWF4T2NjdXJzKG1heE9jY3Vycyk7CiAgICAgICAgCiAgICAgICAgaWYgKGdyb3VwICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5zdGFydFByb2Nlc3NpbmcoZ3JvdXApOwogICAgICAgICAgICByZWRlZmluaXRpb25Gb3IgPSBudWxsOwogICAgICAgICAgICBpZiAoZ3JvdXAuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgICAgIHJlZGVmaW5pdGlvbkZvciA9IG5ldyBSZWRlZmluaXRpb25Gb3JHcm91cChncm91cC5nZXROYW1lKCkpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGhhc0NoaWxkcmVuKQogICAgICAgIHsKICAgICAgICAgICAgWG1sQ3Vyc29yIGN1ciA9IHBhcnNlVHJlZS5uZXdDdXJzb3IoKTsKICAgICAgICAgICAgTGlzdCBhY2N1bXVsYXRlID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgICAgICBmb3IgKGJvb2xlYW4gbW9yZSA9IGN1ci50b0ZpcnN0Q2hpbGQoKTsgbW9yZTsgbW9yZSA9IGN1ci50b05leHRTaWJsaW5nKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGludCBjb2RlID0gdHJhbnNsYXRlUGFydGljbGVDb2RlKGN1ci5nZXROYW1lKCkpOwogICAgICAgICAgICAgICAgaWYgKGNvZGUgPT0gMCkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIGFkZE1pbnVzUG9pbnRsZXNzUGFydGljbGVzKGFjY3VtdWxhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZUNvbnRlbnRNb2RlbChvdXRlclR5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VyLmdldE9iamVjdCgpLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgY29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm9ueW1vdXNUeXBlcywgZWxlbWVudE1vZGVsLCB0cnVlLCByZWRlZmluaXRpb25Gb3IpLAogICAgICAgICAgICAgICAgICAgICAgICBzUGFydC5nZXRQYXJ0aWNsZVR5cGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc1BhcnQuc2V0UGFydGljbGVDaGlsZHJlbigoU2NoZW1hUGFydGljbGVbXSkKICAgICAgICAgICAgICAgICAgICBhY2N1bXVsYXRlLnRvQXJyYXkobmV3IFNjaGVtYVBhcnRpY2xlW2FjY3VtdWxhdGUuc2l6ZSgpXSkpOwogICAgICAgICAgICBjdXIuZGlzcG9zZSgpOwogICAgICAgIH0KICAgICAgICAKCiAgICAgICAgU2NoZW1hUGFydGljbGUgcmVzdWx0ID0gZmlsdGVyUG9pbnRsZXNzUGFydGljbGVzQW5kVmVyaWZ5QWxsUGFydGljbGVzKHNQYXJ0LCBwYXJzZVRyZWUpOwoKICAgICAgICBpZiAoZ3JvdXAgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmZpbmlzaFByb2Nlc3NpbmcoZ3JvdXApOwogICAgICAgIH0KICAgICAgICAvLyBvdXRkZW50REJHKCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIAogICAgc3RhdGljIGludCB0cmFuc2xhdGVXaWxkY2FyZFByb2Nlc3MoQW55LlByb2Nlc3NDb250ZW50cyBwcm9jZXNzKQogICAgewogICAgICAgIGlmIChwcm9jZXNzID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBTY2hlbWFQYXJ0aWNsZS5TVFJJQ1Q7CgogICAgICAgIFN0cmluZyBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzLmdldFN0cmluZ1ZhbHVlKCk7CgogICAgICAgIGlmICgibGF4Ii5lcXVhbHMocHJvY2Vzc1ZhbHVlKSkKICAgICAgICAgICAgcmV0dXJuIFNjaGVtYVBhcnRpY2xlLkxBWDsKCiAgICAgICAgaWYgKCJza2lwIi5lcXVhbHMocHJvY2Vzc1ZhbHVlKSkKICAgICAgICAgICAgcmV0dXJuIFNjaGVtYVBhcnRpY2xlLlNLSVA7CgogICAgICAgIHJldHVybiBTY2hlbWFQYXJ0aWNsZS5TVFJJQ1Q7CiAgICB9CgogICAgc3RhdGljIFNjaGVtYVBhcnRpY2xlIGZpbHRlclBvaW50bGVzc1BhcnRpY2xlc0FuZFZlcmlmeUFsbFBhcnRpY2xlcyhTY2hlbWFQYXJ0aWNsZSBwYXJ0LCBYbWxPYmplY3QgcGFyc2VUcmVlKQogICAgewogICAgICAgIGlmIChwYXJ0LmdldE1heE9jY3VycygpICE9IG51bGwgJiYgcGFydC5nZXRNYXhPY2N1cnMoKS5zaWdudW0oKSA9PSAwKQogICAgICAgICAgICByZXR1cm4gbnVsbDsKCiAgICAgICAgc3dpdGNoIChwYXJ0LmdldFBhcnRpY2xlVHlwZSgpKQogICAgICAgIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICBpZiAocGFydC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCkubGVuZ3RoID09IDApCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICBpZiAocGFydC5pc1NpbmdsZXRvbigpICYmIHBhcnQuY291bnRPZlBhcnRpY2xlQ2hpbGQoKSA9PSAxKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0LmdldFBhcnRpY2xlQ2hpbGQoMCk7CiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQ0hPSUNFOgogICAgICAgICAgICAgICAgaWYgKHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpLmxlbmd0aCA9PSAwICYmCiAgICAgICAgICAgICAgICAgICAgcGFydC5nZXRNaW5PY2N1cnMoKS5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSA9PSAwKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgaWYgKHBhcnQuaXNTaW5nbGV0b24oKSAmJiBwYXJ0LmNvdW50T2ZQYXJ0aWNsZUNoaWxkKCkgPT0gMSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFydC5nZXRQYXJ0aWNsZUNoaWxkKDApOwogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICByZXR1cm4gcGFydDsKCiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBpZiAoWG1sQmVhbnMuQVNTRVJUUykKICAgICAgICAgICAgICAgICAgICBYbWxCZWFucy5hc3NlcnRUcnVlKGZhbHNlKTsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgYm9vbGVhbiBpc0FsbCA9IHBhcnQuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMOwogICAgICAgIAogICAgICAgIGlmIChpc0FsbCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3htbHNjaGVtYS0xLyNjb3MtYWxsLWxpbWl0ZWQKICAgICAgICAgICAgaWYgKHBhcnQuZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCB8fCBwYXJ0LmdldE1heE9jY3VycygpLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPiAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIkFuIGFsbCBncm91cCBtdXN0IGhhdmUgbWF4T2NjdXJzIDw9IDEiLCBYbWxFcnJvckNvbnRleHQuQUxMX0NPTlRFTlRTLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFydC5jb3VudE9mUGFydGljbGVDaGlsZCgpOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBjaGlsZCA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZChpKTsKICAgICAgICAgICAgaWYgKGNoaWxkLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkFMTCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJBbiBhbGwgZ3JvdXAgaXMgb25seSBhbGxvd2VkIGF0IHRoZSB0b3AgbGV2ZWwgb2YgdGhlIGNvbnRlbnQgbW9kZWwiLCBYbWxFcnJvckNvbnRleHQuQ0FOTk9UX0VYVEVORF9BTEwsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoaXNBbGwgJiYgKGNoaWxkLmdldFBhcnRpY2xlVHlwZSgpICE9IFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQgfHwgY2hpbGQuZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCB8fCBjaGlsZC5nZXRNYXhPY2N1cnMoKS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID4gMCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQW4gYWxsIGdyb3VwIGNhbiBjb250YWluIG9ubHkgZWxlbWVudCBwYXJ0aWNsZXMgd2l0aCBtYXhPY2N1cnMgPD0gMSIsIFhtbEVycm9yQ29udGV4dC5BTExfQ09OVEVOVFMsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHBhcnQ7CiAgICB9CgogICAgc3RhdGljIHZvaWQgYWRkTWludXNQb2ludGxlc3NQYXJ0aWNsZXMoCiAgICAgICAgICAgIExpc3QgbGlzdCwgU2NoZW1hUGFydGljbGUgcGFydCwgaW50IHBhcmVudFBhcnRpY2xlVHlwZSkKICAgIHsKICAgICAgICBpZiAocGFydCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm47CgogICAgICAgIHN3aXRjaCAocGFydC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICBpZiAocGFyZW50UGFydGljbGVUeXBlID09IFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFICYmIHBhcnQuaXNTaW5nbGV0b24oKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvLyBlbWl0REJHKCJkcm9wcGluZyByZWR1bmRhbnQgc2VxdWVuY2UiKTsKICAgICAgICAgICAgICAgICAgICBsaXN0LmFkZEFsbChBcnJheXMuYXNMaXN0KHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpKSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgIGlmIChwYXJlbnRQYXJ0aWNsZVR5cGUgPT0gU2NoZW1hUGFydGljbGUuQ0hPSUNFICYmIHBhcnQuaXNTaW5nbGV0b24oKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvLyBlbWl0REJHKCJkcm9wcGluZyByZWR1bmRhbnQgY2hvaWNlIik7CiAgICAgICAgICAgICAgICAgICAgbGlzdC5hZGRBbGwoQXJyYXlzLmFzTGlzdChwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKSkpOwogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICBkZWZhdWx0OiAgICAgICAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgbGlzdC5hZGQocGFydCk7CiAgICB9CgogICAgc3RhdGljIE1hcCBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKFNjaGVtYUF0dHJpYnV0ZU1vZGVsIGF0dHJNb2RlbCwgU2NoZW1hVHlwZSBvd25lcikKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IFNlcXVlbmNlZEhhc2hNYXAoKTsKICAgICAgICBTY2hlbWFMb2NhbEF0dHJpYnV0ZVtdIGF0dHJ1c2VzID0gYXR0ck1vZGVsLmdldEF0dHJpYnV0ZXMoKTsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBhdHRydXNlcy5sZW5ndGg7IGkrKykKICAgICAgICAgICAgcmVzdWx0LnB1dChhdHRydXNlc1tpXS5nZXROYW1lKCksIGJ1aWxkVXNlUHJvcGVydHkoYXR0cnVzZXNbaV0sIG93bmVyKSk7CgogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CgogICAgc3RhdGljIE1hcCBidWlsZENvbnRlbnRQcm9wZXJ0eU1vZGVsQnlRTmFtZShTY2hlbWFQYXJ0aWNsZSBwYXJ0LCBTY2hlbWFUeXBlIG93bmVyKQogICAgewogICAgICAgIGlmIChwYXJ0ID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBDb2xsZWN0aW9ucy5FTVBUWV9NQVA7CgogICAgICAgIGJvb2xlYW4gYXNTZXF1ZW5jZSA9IGZhbHNlOwogICAgICAgIE1hcCBtb2RlbCA9IG51bGw7CgogICAgICAgIHN3aXRjaCAocGFydC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgYXNTZXF1ZW5jZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBhc1NlcXVlbmNlID0gZmFsc2U7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgbW9kZWwgPSBidWlsZEVsZW1lbnRQcm9wZXJ0eU1vZGVsKChTY2hlbWFMb2NhbEVsZW1lbnQpcGFydCwgb3duZXIpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICBtb2RlbCA9IENvbGxlY3Rpb25zLkVNUFRZX01BUDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgaWYgKFhtbEJlYW5zLkFTU0VSVFMpCiAgICAgICAgICAgICAgICAgICAgWG1sQmVhbnMuYXNzZXJ0VHJ1ZShmYWxzZSk7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAobW9kZWwgPT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIGJ1aWxkIG1vZGVsIGZvciBjaGlsZHJlbgogICAgICAgICAgICBtb2RlbCA9IG5ldyBTZXF1ZW5jZWRIYXNoTWFwKCk7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKCiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIGluZGVudERCRygpOwogICAgICAgICAgICAgICAgTWFwIGNoaWxkTW9kZWwgPSBidWlsZENvbnRlbnRQcm9wZXJ0eU1vZGVsQnlRTmFtZShjaGlsZHJlbltpXSwgb3duZXIpOwogICAgICAgICAgICAgICAgLy8gb3V0ZGVudERCRygpOwogICAgICAgICAgICAgICAgZm9yIChJdGVyYXRvciBqID0gY2hpbGRNb2RlbC52YWx1ZXMoKS5pdGVyYXRvcigpOyBqLmhhc05leHQoKTsgKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNjaGVtYVByb3BlcnR5IGlQcm9wID0gKFNjaGVtYVByb3BlcnR5KWoubmV4dCgpOwogICAgICAgICAgICAgICAgICAgIFNjaGVtYVByb3BlcnR5SW1wbCBvUHJvcCA9IChTY2hlbWFQcm9wZXJ0eUltcGwpbW9kZWwuZ2V0KGlQcm9wLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKG9Qcm9wID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFzU2VxdWVuY2UpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKFNjaGVtYVByb3BlcnR5SW1wbClpUHJvcCkuc2V0TWluT2NjdXJzKEJpZ0ludGVnZXIuWkVSTyk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsLnB1dChpUHJvcC5nZXROYW1lKCksIGlQcm9wKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIC8vIGNvbnNpc3RlbmN5IHZlcmlmaWVkIGluIGFuIGVhcmxpZXIgc3RlcAogICAgICAgICAgICAgICAgICAgIGlmIChYbWxCZWFucy5BU1NFUlRTKQogICAgICAgICAgICAgICAgICAgICAgICBYbWxCZWFucy5hc3NlcnRUcnVlKG9Qcm9wLmdldFR5cGUoKS5lcXVhbHMoaVByb3AuZ2V0VHlwZSgpKSk7CgogICAgICAgICAgICAgICAgICAgIG1lcmdlUHJvcGVydGllcyhvUHJvcCwgaVByb3AsIGFzU2VxdWVuY2UpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBmaW5hbGx5IGRlYWwgd2l0aCBtaW5PY2N1cnMsIG1heE9jY3VycyBvdmVyIHdob2xlIGdyb3VwCiAgICAgICAgICAgIEJpZ0ludGVnZXIgbWluID0gcGFydC5nZXRNaW5PY2N1cnMoKTsKICAgICAgICAgICAgQmlnSW50ZWdlciBtYXggPSBwYXJ0LmdldE1heE9jY3VycygpOwoKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBqID0gbW9kZWwudmFsdWVzKCkuaXRlcmF0b3IoKTsgai5oYXNOZXh0KCk7ICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgU2NoZW1hUHJvcGVydHkgb1Byb3AgPSAoU2NoZW1hUHJvcGVydHkpai5uZXh0KCk7CiAgICAgICAgICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VycyA9IG9Qcm9wLmdldE1pbk9jY3VycygpOwogICAgICAgICAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBvUHJvcC5nZXRNYXhPY2N1cnMoKTsKCiAgICAgICAgICAgICAgICBtaW5PY2N1cnMgPSBtaW5PY2N1cnMubXVsdGlwbHkobWluKTsKICAgICAgICAgICAgICAgIGlmIChtYXggIT0gbnVsbCAmJiBtYXguZXF1YWxzKEJpZ0ludGVnZXIuWkVSTykpCiAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzID0gQmlnSW50ZWdlci5aRVJPOwogICAgICAgICAgICAgICAgZWxzZSBpZiAobWF4T2NjdXJzICE9IG51bGwgJiYgIW1heE9jY3Vycy5lcXVhbHMoQmlnSW50ZWdlci5aRVJPKSkKICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnMgPSBtYXggPT0gbnVsbCA/IG51bGwgOiBtYXhPY2N1cnMubXVsdGlwbHkobWF4KTsKCiAgICAgICAgICAgICAgICAoKFNjaGVtYVByb3BlcnR5SW1wbClvUHJvcCkuc2V0TWluT2NjdXJzKG1pbk9jY3Vycyk7CiAgICAgICAgICAgICAgICAoKFNjaGVtYVByb3BlcnR5SW1wbClvUHJvcCkuc2V0TWF4T2NjdXJzKG1heE9jY3Vycyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBtb2RlbDsKICAgIH0KCiAgICBzdGF0aWMgTWFwIGJ1aWxkRWxlbWVudFByb3BlcnR5TW9kZWwoU2NoZW1hTG9jYWxFbGVtZW50IGVwYXJ0LCBTY2hlbWFUeXBlIG93bmVyKQogICAgewogICAgICAgIE1hcCByZXN1bHQgPSBuZXcgSGFzaE1hcCgxKTsKCiAgICAgICAgU2NoZW1hUHJvcGVydHkgc1Byb3AgPSBidWlsZFVzZVByb3BlcnR5KGVwYXJ0LCBvd25lcik7CiAgICAgICAgcmVzdWx0LnB1dChzUHJvcC5nZXROYW1lKCksIHNQcm9wKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIHN0YXRpYyBTY2hlbWFQcm9wZXJ0eSBidWlsZFVzZVByb3BlcnR5KFNjaGVtYUZpZWxkIHVzZSwgU2NoZW1hVHlwZSBvd25lcikKICAgIHsKICAgICAgICBTY2hlbWFQcm9wZXJ0eUltcGwgc1Byb3BJbXBsID0gbmV3IFNjaGVtYVByb3BlcnR5SW1wbCgpOwogICAgICAgIHNQcm9wSW1wbC5zZXROYW1lKHVzZS5nZXROYW1lKCkpOwogICAgICAgIHNQcm9wSW1wbC5zZXRDb250YWluZXJUeXBlUmVmKG93bmVyLmdldFJlZigpKTsKICAgICAgICBzUHJvcEltcGwuc2V0VHlwZVJlZih1c2UuZ2V0VHlwZSgpLmdldFJlZigpKTsKICAgICAgICBzUHJvcEltcGwuc2V0QXR0cmlidXRlKHVzZS5pc0F0dHJpYnV0ZSgpKTsKICAgICAgICBzUHJvcEltcGwuc2V0RGVmYXVsdCh1c2UuaXNEZWZhdWx0KCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldEZpeGVkKHVzZS5pc0ZpeGVkKCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldE5pbGxhYmxlKHVzZS5pc05pbGxhYmxlKCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldERlZmF1bHRUZXh0KHVzZS5nZXREZWZhdWx0VGV4dCgpKTsKICAgICAgICBzUHJvcEltcGwuc2V0TWluT2NjdXJzKHVzZS5nZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgc1Byb3BJbXBsLnNldE1heE9jY3Vycyh1c2UuZ2V0TWF4T2NjdXJzKCkpOwoKICAgICAgICBpZiAodXNlIGluc3RhbmNlb2YgU2NoZW1hTG9jYWxFbGVtZW50SW1wbCkKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYUxvY2FsRWxlbWVudEltcGwgZWx0ID0gKFNjaGVtYUxvY2FsRWxlbWVudEltcGwpdXNlOwogICAgICAgICAgICBzUHJvcEltcGwuc2V0QWNjZXB0ZWROYW1lcyhlbHQuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHNQcm9wSW1wbDsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCBtZXJnZVByb3BlcnRpZXMoU2NoZW1hUHJvcGVydHlJbXBsIGludG8sIFNjaGVtYVByb3BlcnR5IGZyb20sIGJvb2xlYW4gYXNTZXF1ZW5jZSkKICAgIHsKICAgICAgICAvLyBtaW5vY2N1ciwgbWF4b2NjdXIKICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VycyA9IGludG8uZ2V0TWluT2NjdXJzKCk7CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBpbnRvLmdldE1heE9jY3VycygpOwogICAgICAgIGlmIChhc1NlcXVlbmNlKQogICAgICAgIHsKICAgICAgICAgICAgbWluT2NjdXJzID0gbWluT2NjdXJzLmFkZChmcm9tLmdldE1pbk9jY3VycygpKTsKICAgICAgICAgICAgaWYgKG1heE9jY3VycyAhPSBudWxsKQogICAgICAgICAgICAgICAgbWF4T2NjdXJzID0gKGZyb20uZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCA/IG51bGwgOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzLmFkZChmcm9tLmdldE1heE9jY3VycygpKSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIG1pbk9jY3VycyA9IG1pbk9jY3Vycy5taW4oZnJvbS5nZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgICAgIGlmIChtYXhPY2N1cnMgIT0gbnVsbCkKICAgICAgICAgICAgICAgIG1heE9jY3VycyA9IChmcm9tLmdldE1heE9jY3VycygpID09IG51bGwgPyBudWxsIDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnMubWF4KGZyb20uZ2V0TWF4T2NjdXJzKCkpKTsKICAgICAgICB9CiAgICAgICAgaW50by5zZXRNaW5PY2N1cnMobWluT2NjdXJzKTsKICAgICAgICBpbnRvLnNldE1heE9jY3VycyhtYXhPY2N1cnMpOwoKICAgICAgICAvLyBuaWxsYWJsZSwgZGVmYXVsdCwgZml4ZWQKICAgICAgICBpZiAoZnJvbS5oYXNOaWxsYWJsZSgpICE9IGludG8uaGFzTmlsbGFibGUoKSkKICAgICAgICAgICAgaW50by5zZXROaWxsYWJsZShTY2hlbWFQcm9wZXJ0eS5WQVJJQUJMRSk7CiAgICAgICAgaWYgKGZyb20uaGFzRGVmYXVsdCgpICE9IGludG8uaGFzRGVmYXVsdCgpKQogICAgICAgICAgICBpbnRvLnNldERlZmF1bHQoU2NoZW1hUHJvcGVydHkuVkFSSUFCTEUpOwogICAgICAgIGlmIChmcm9tLmhhc0ZpeGVkKCkgIT0gaW50by5oYXNGaXhlZCgpKQogICAgICAgICAgICBpbnRvLnNldEZpeGVkKFNjaGVtYVByb3BlcnR5LlZBUklBQkxFKTsKCiAgICAgICAgLy8gZGVmYXVsdCB2YWx1ZQogICAgICAgIGlmIChpbnRvLmdldERlZmF1bHRUZXh0KCkgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChmcm9tLmdldERlZmF1bHRUZXh0KCkgPT0gbnVsbCB8fAogICAgICAgICAgICAgICAgIWludG8uZ2V0RGVmYXVsdFRleHQoKS5lcXVhbHMoZnJvbS5nZXREZWZhdWx0VGV4dCgpKSkKICAgICAgICAgICAgICAgIGludG8uc2V0RGVmYXVsdFRleHQobnVsbCk7CiAgICAgICAgfQogICAgfQoKICAgIHN0YXRpYyBTY2hlbWFQYXJ0aWNsZVtdIGVuc3VyZVN0YXRlTWFjaGluZShTY2hlbWFQYXJ0aWNsZVtdIGNoaWxkcmVuKQogICAgewogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBidWlsZFN0YXRlTWFjaGluZShjaGlsZHJlbltpXSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjaGlsZHJlbjsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCBidWlsZFN0YXRlTWFjaGluZShTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwpCiAgICB7CiAgICAgICAgaWYgKGNvbnRlbnRNb2RlbCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm47CgogICAgICAgIFNjaGVtYVBhcnRpY2xlSW1wbCBwYXJ0SW1wbCA9IChTY2hlbWFQYXJ0aWNsZUltcGwpY29udGVudE1vZGVsOwogICAgICAgIGlmIChwYXJ0SW1wbC5oYXNUcmFuc2l0aW9uTm90ZXMoKSkKICAgICAgICAgICAgcmV0dXJuOwoKICAgICAgICBRTmFtZVNldEJ1aWxkZXIgc3RhcnQgPSBuZXcgUU5hbWVTZXRCdWlsZGVyKCk7CiAgICAgICAgUU5hbWVTZXRCdWlsZGVyIGV4Y2x1ZGVuZXh0ID0gbmV3IFFOYW1lU2V0QnVpbGRlcigpOwogICAgICAgIGJvb2xlYW4gZGV0ZXJtaW5pc3RpYyA9IHRydWU7CiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IG51bGw7CiAgICAgICAgYm9vbGVhbiBjYW5za2lwID0gKHBhcnRJbXBsLmdldE1pbk9jY3VycygpLnNpZ251bSgpID09IDApOwoKICAgICAgICBzd2l0Y2ggKHBhcnRJbXBsLmdldFBhcnRpY2xlVHlwZSgpKQogICAgICAgIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgLy8gY29tcHV0ZSBzdGFydCBhbmQgZXhjbHVkZU5leHQ7IGNhbnNraXAgaXMgYWxyZWFkeSBjb3JyZWN0CiAgICAgICAgICAgICAgICBpZiAocGFydEltcGwuaGFzVHJhbnNpdGlvblJ1bGVzKCkpCiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKHBhcnRJbXBsLmFjY2VwdGVkU3RhcnROYW1lcygpKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICBzdGFydC5hZGQocGFydEltcGwuZ2V0TmFtZSgpKTsKCiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICAvLyBjb21wdXRlIHN0YXJ0IGFuZCBleGNsdWRlTmV4dDsgY2Fuc2tpcCBpcyBhbHJlYWR5IGNvcnJlY3QKICAgICAgICAgICAgICAgIHN0YXJ0LmFkZEFsbChwYXJ0SW1wbC5nZXRXaWxkY2FyZFNldCgpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gZW5zdXJlU3RhdGVNYWNoaW5lKHBhcnRJbXBsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKSk7CgogICAgICAgICAgICAgICAgLy8gYWRqdXN0IGNhbnNraXAgaWYgYWxsIGNoaWxkcmVuIGFyZSBza2lwcGFibGUKICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGNhbnNraXAgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKGNoaWxkcmVuW2ldKS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICBjYW5za2lwID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIHZlcmlmeSBkZXRlcm1pbmlzdGljIGFuZCBjb21wdXRlIGV4Y2x1ZGVOZXh0IHNldAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBleGNsdWRlbmV4dC5hZGRBbGwoKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baSAtIDFdKS5nZXRFeGNsdWRlTmV4dFNldCgpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZGV0ZXJtaW5pc3RpYyAmJiAhZXhjbHVkZW5leHQuaXNEaXNqb2ludCgoY2hpbGRyZW5baV0pLmFjY2VwdGVkU3RhcnROYW1lcygpKSkKICAgICAgICAgICAgICAgICAgICAgICAgZGV0ZXJtaW5pc3RpYyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmICgoY2hpbGRyZW5baV0pLmlzU2tpcHBhYmxlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoY2hpbGRyZW5baV0pLmFjY2VwdGVkU3RhcnROYW1lcygpKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmNsZWFyKCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLy8gbmV4dCwgY29tcHV0ZSBzdGFydCBzZXQKICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGlmICghKGNoaWxkcmVuW2ldKS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IGVuc3VyZVN0YXRlTWFjaGluZShwYXJ0SW1wbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCkpOwoKICAgICAgICAgICAgICAgIC8vIGFkanVzdCBjYW5za2lwIGlmIGFueSBjaGlsZHJlbiBhcmUgc2tpcHBhYmxlCiAgICAgICAgICAgICAgICBjYW5za2lwID0gZmFsc2U7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgIWNhbnNraXAgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICgoY2hpbGRyZW5baV0pLmlzU2tpcHBhYmxlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgc3RhcnQgYW5kIGV4Y2x1ZGVOZXh0IHNldHMsIHZlcmlmeSBkZXRlcm1pbmlzdGljCiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChkZXRlcm1pbmlzdGljICYmICFzdGFydC5pc0Rpc2pvaW50KChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoKFNjaGVtYVBhcnRpY2xlSW1wbCljaGlsZHJlbltpXSkuZ2V0RXhjbHVkZU5leHRTZXQoKSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gZW5zdXJlU3RhdGVNYWNoaW5lKHBhcnRJbXBsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKSk7CgogICAgICAgICAgICAgICAgLy8gYWRqdXN0IGNhbnNraXAgaWYgYWxsIGNoaWxkcmVuIGFyZSBza2lwcGFibGUKICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7ICFjYW5za2lwICYmIGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIShjaGlsZHJlbltpXSkuaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgY2Fuc2tpcCA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgc3RhcnQgYW5kIGV4Y2x1ZGVOZXh0IHNldHMsIHZlcmlmeSBkZXRlcm1pbmlzdGljCiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChkZXRlcm1pbmlzdGljICYmICFzdGFydC5pc0Rpc2pvaW50KChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoKFNjaGVtYVBhcnRpY2xlSW1wbCljaGlsZHJlbltpXSkuZ2V0RXhjbHVkZU5leHRTZXQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoY2Fuc2tpcCkKICAgICAgICAgICAgICAgICAgICBleGNsdWRlbmV4dC5hZGRBbGwoc3RhcnQpOwoKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIC8vIHdpbGRjYXJkLCBhbGwgY2FzZXMgbnlpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJVbnJlY29nbml6ZWQgc2NoZW1hIHBhcnRpY2xlIik7CiAgICAgICAgfQoKICAgICAgICAvLyBhcHBseSBsb29waW5nIGxvZ2ljCgogICAgICAgIEJpZ0ludGVnZXIgbWluT2NjdXJzID0gcGFydEltcGwuZ2V0TWluT2NjdXJzKCk7CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBwYXJ0SW1wbC5nZXRNYXhPY2N1cnMoKTsKICAgICAgICBib29sZWFuIGNhbmxvb3AgPSAobWF4T2NjdXJzID09IG51bGwgfHwgbWF4T2NjdXJzLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPiAwKTsKICAgICAgICBib29sZWFuIHZhcmxvb3AgPSAobWF4T2NjdXJzID09IG51bGwgfHwgbWluT2NjdXJzLmNvbXBhcmVUbyhtYXhPY2N1cnMpIDwgMCk7CgogICAgICAgIGlmIChjYW5sb29wICYmIGRldGVybWluaXN0aWMgJiYgIWV4Y2x1ZGVuZXh0LmlzRGlzam9pbnQoc3RhcnQpKQogICAgICAgIHsKICAgICAgICAgICAgLy8gd2UgaGF2ZSBhIHBvc3NpYmxlIGxvb3Bpbmcgbm9uZGV0ZXJtaW5pc20uCiAgICAgICAgICAgIC8vIGxldCdzIHRha2Ugc29tZSB0aW1lIG5vdyB0byBzZWUgaWYgaXQncyBhY3R1YWxseSBjYXVzZWQKICAgICAgICAgICAgLy8gYnkgbm9uLXVuaXF1ZS1wYXJ0aWNsZS1hdHRyaWJ1dGUgb3Igbm90LgogICAgICAgICAgICBRTmFtZVNldCBzdXNwZWN0U2V0ID0gZXhjbHVkZW5leHQuaW50ZXJzZWN0KHN0YXJ0KTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIGNvbXB1dGUgdGhlIHNldCBvZiBhbGwgcGFydGljbGVzIHRoYXQgY291bGQgc3RhcnQgdGhpcyBncm91cAogICAgICAgICAgICBNYXAgc3RhcnRNYXAgPSBuZXcgSGFzaE1hcCgpOwogICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KHBhcnRJbXBsLCBzdXNwZWN0U2V0LCBzdGFydE1hcCwgbmV3IFFOYW1lU2V0QnVpbGRlcigpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIGNvbXB1dGUgdGhlIHNldCBvZiBhbGwgcGFydGljbGVzIHRoYXQgY291bGQgaGF2ZSBiZWVuIHJlcGVhdGVkIHJhdGhlciB0aGFuIGVuZGluZyB0aGlzIGdyb3VwCiAgICAgICAgICAgIE1hcCBhZnRlck1hcCA9IG5ldyBIYXNoTWFwKCk7CiAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nQWZ0ZXIocGFydEltcGwsIHN1c3BlY3RTZXQsIGFmdGVyTWFwLCBuZXcgUU5hbWVTZXRCdWlsZGVyKCksIHRydWUpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gc2VlIGlmIHdlIGNhbiBmaW5kIGEgbWVtYmVyIG9mIGFmdGVyIHRoYXQgaXMgbm90IGEgbWVtYmVyIG9mIHN0YXJ0CiAgICAgICAgICAgIC8vIGlmIHdlIGNhbiwgdGhlbiBwYXJ0aWNsZSBhdHRyaWJ1dGlvbiBpcyBub3QgdW5pcXVlCiAgICAgICAgICAgIGRldGVybWluaXN0aWMgPSBhZnRlck1hcFN1YnN1bWVkQnlTdGFydE1hcChzdGFydE1hcCwgYWZ0ZXJNYXApOwogICAgICAgIH0KCiAgICAgICAgaWYgKHZhcmxvb3ApCiAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbChzdGFydCk7CgogICAgICAgIGNhbnNraXAgPSBjYW5za2lwIHx8IG1pbk9jY3Vycy5zaWdudW0oKSA9PSAwOwoKICAgICAgICBwYXJ0SW1wbC5zZXRUcmFuc2l0aW9uUnVsZXMoc3RhcnQudG9RTmFtZVNldCgpLCBjYW5za2lwKTsKICAgICAgICBwYXJ0SW1wbC5zZXRUcmFuc2l0aW9uTm90ZXMoZXhjbHVkZW5leHQudG9RTmFtZVNldCgpLCBkZXRlcm1pbmlzdGljKTsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBhZnRlck1hcFN1YnN1bWVkQnlTdGFydE1hcChNYXAgc3RhcnRNYXAsIE1hcCBhZnRlck1hcCkKICAgIHsKICAgICAgICBpZiAoYWZ0ZXJNYXAuc2l6ZSgpID4gc3RhcnRNYXAuc2l6ZSgpKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgCiAgICAgICAgaWYgKGFmdGVyTWFwLmlzRW1wdHkoKSkKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgCiAgICAgICAgZm9yIChJdGVyYXRvciBpID0gc3RhcnRNYXAua2V5U2V0KCkuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7ICkKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlIHBhcnQgPSAoU2NoZW1hUGFydGljbGUpaS5uZXh0KCk7CiAgICAgICAgICAgIGlmIChwYXJ0LmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLldJTERDQVJEKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoYWZ0ZXJNYXAuY29udGFpbnNLZXkocGFydCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgUU5hbWVTZXQgc3RhcnRTZXQgPSAoUU5hbWVTZXQpc3RhcnRNYXAuZ2V0KHBhcnQpOwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0IGFmdGVyU2V0ID0gKFFOYW1lU2V0KWFmdGVyTWFwLmdldChwYXJ0KTsKICAgICAgICAgICAgICAgICAgICBpZiAoIXN0YXJ0U2V0LmNvbnRhaW5zQWxsKGFmdGVyU2V0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGFmdGVyTWFwLnJlbW92ZShwYXJ0KTsKICAgICAgICAgICAgaWYgKGFmdGVyTWFwLmlzRW1wdHkoKSkKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKGFmdGVyTWFwLmlzRW1wdHkoKSk7CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgcGFydGljbGVzTWF0Y2hpbmdTdGFydChTY2hlbWFQYXJ0aWNsZSBwYXJ0LCBRTmFtZVNldFNwZWNpZmljYXRpb24gc3VzcGVjdFNldCwgTWFwIHJlc3VsdCwgUU5hbWVTZXRCdWlsZGVyIGVsaW1pbmF0ZSkKICAgIHsKICAgICAgICBzd2l0Y2ggKHBhcnQuZ2V0UGFydGljbGVUeXBlKCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgICAgICBpZiAoIXN1c3BlY3RTZXQuY29udGFpbnMocGFydC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydCwgbnVsbCk7CiAgICAgICAgICAgICAgICBlbGltaW5hdGUuYWRkKHBhcnQuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgaWYgKHN1c3BlY3RTZXQuaXNEaXNqb2ludChwYXJ0LmdldFdpbGRjYXJkU2V0KCkpKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydCwgcGFydC5nZXRXaWxkY2FyZFNldCgpLmludGVyc2VjdChzdXNwZWN0U2V0KSk7CiAgICAgICAgICAgICAgICBlbGltaW5hdGUuYWRkQWxsKHBhcnQuZ2V0V2lsZGNhcmRTZXQoKSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KGNoaWxkcmVuW2ldLCBzdXNwZWN0U2V0LCByZXN1bHQsIGVsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW5bMF0uaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nU3RhcnQoY2hpbGRyZW5bMF0sIHN1c3BlY3RTZXQsIHJlc3VsdCwgZWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBRTmFtZVNldEJ1aWxkZXIgcmVtYWluaW5nU3VzcGVjdHMgPSBuZXcgUU5hbWVTZXRCdWlsZGVyKHN1c3BlY3RTZXQpOwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0QnVpbGRlciBzdXNwZWN0c1RvRWxpbWluYXRlID0gbmV3IFFOYW1lU2V0QnVpbGRlcigpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KGNoaWxkcmVuW2ldLCByZW1haW5pbmdTdXNwZWN0cywgcmVzdWx0LCBzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxpbWluYXRlLmFkZEFsbChzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbltpXS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICByZW1haW5pbmdTdXNwZWN0cy5yZW1vdmVBbGwoc3VzcGVjdHNUb0VsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZW1haW5pbmdTdXNwZWN0cy5pc0VtcHR5KCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlY3RzVG9FbGltaW5hdGUuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgdm9pZCBwYXJ0aWNsZXNNYXRjaGluZ0FmdGVyKFNjaGVtYVBhcnRpY2xlIHBhcnQsIFFOYW1lU2V0U3BlY2lmaWNhdGlvbiBzdXNwZWN0U2V0LCBNYXAgcmVzdWx0LCBRTmFtZVNldEJ1aWxkZXIgZWxpbWluYXRlLCBib29sZWFuIHRvcCkKICAgIHsKICAgICAgICByZWN1cnNlOiBzd2l0Y2ggKHBhcnQuZ2V0UGFydGljbGVUeXBlKCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nQWZ0ZXIoY2hpbGRyZW5baV0sIHN1c3BlY3RTZXQsIHJlc3VsdCwgZWxpbWluYXRlLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09IDApCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxXS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgcGFydGljbGVzTWF0Y2hpbmdBZnRlcihjaGlsZHJlblswXSwgc3VzcGVjdFNldCwgcmVzdWx0LCBlbGltaW5hdGUsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgUU5hbWVTZXRCdWlsZGVyIHJlbWFpbmluZ1N1c3BlY3RzID0gbmV3IFFOYW1lU2V0QnVpbGRlcihzdXNwZWN0U2V0KTsKICAgICAgICAgICAgICAgICAgICBRTmFtZVNldEJ1aWxkZXIgc3VzcGVjdHNUb0VsaW1pbmF0ZSA9IG5ldyBRTmFtZVNldEJ1aWxkZXIoKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ0FmdGVyKGNoaWxkcmVuW2ldLCByZW1haW5pbmdTdXNwZWN0cywgcmVzdWx0LCBzdXNwZWN0c1RvRWxpbWluYXRlLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsaW1pbmF0ZS5hZGRBbGwoc3VzcGVjdHNUb0VsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW5baV0uaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlbWFpbmluZ1N1c3BlY3RzLnJlbW92ZUFsbChzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1N1c3BlY3RzLmlzRW1wdHkoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlY3RzVG9FbGltaW5hdGUuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICghdG9wKQogICAgICAgIHsKICAgICAgICAgICAgQmlnSW50ZWdlciBtaW5PY2N1cnMgPSBwYXJ0LmdldE1pbk9jY3VycygpOwogICAgICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3VycyA9IHBhcnQuZ2V0TWF4T2NjdXJzKCk7CiAgICAgICAgICAgIGJvb2xlYW4gdmFybG9vcCA9IChtYXhPY2N1cnMgPT0gbnVsbCB8fCBtaW5PY2N1cnMuY29tcGFyZVRvKG1heE9jY3VycykgPCAwKTsKICAgICAgICAgICAgaWYgKHZhcmxvb3ApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nU3RhcnQocGFydCwgc3VzcGVjdFNldCwgcmVzdWx0LCBlbGltaW5hdGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGNsYXNzIENvZGVGb3JOYW1lRW50cnkKICAgIHsKICAgICAgICBDb2RlRm9yTmFtZUVudHJ5KFFOYW1lIG5hbWUsIGludCBjb2RlKQogICAgICAgICAgICB7IHRoaXMubmFtZSA9IG5hbWU7IHRoaXMuY29kZSA9IGNvZGU7IH0KICAgICAgICBwdWJsaWMgUU5hbWUgbmFtZTsKICAgICAgICBwdWJsaWMgaW50IGNvZGU7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgaW50IE1PREVMX0dST1VQX0NPREUgPSAxMDA7CgogICAgcHJpdmF0ZSBzdGF0aWMgQ29kZUZvck5hbWVFbnRyeVtdIHBhcnRpY2xlQ29kZXMgPSBuZXcgQ29kZUZvck5hbWVFbnRyeVtdCiAgICB7CiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhbGwiLCAiaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiKSwgU2NoZW1hUGFydGljbGUuQUxMKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoInNlcXVlbmNlIiwgImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiksIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImNob2ljZSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0UpLAogICAgICAgIG5ldyBDb2RlRm9yTmFtZUVudHJ5KFFOYW1lSGVscGVyLmZvckxOUygiZWxlbWVudCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImFueSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRCksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJncm91cCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBNT0RFTF9HUk9VUF9DT0RFKSwKICAgIH07CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIHBhcnRpY2xlQ29kZU1hcCA9IGJ1aWxkUGFydGljbGVDb2RlTWFwKCk7CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIGJ1aWxkUGFydGljbGVDb2RlTWFwKCkKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhcnRpY2xlQ29kZXMubGVuZ3RoOyBpKyspCiAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydGljbGVDb2Rlc1tpXS5uYW1lLCAgbmV3IEludGVnZXIocGFydGljbGVDb2Rlc1tpXS5jb2RlKSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBpbnQgdHJhbnNsYXRlUGFydGljbGVDb2RlKEdyb3VwIHBhcnNlRWcpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlRWcgPT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgcmV0dXJuIHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShwYXJzZUVnLm5ld0N1cnNvcigpLmdldE5hbWUoKSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgaW50IHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShRTmFtZSBuYW1lKQogICAgewogICAgICAgIEludGVnZXIgcmVzdWx0ID0gKEludGVnZXIpcGFydGljbGVDb2RlTWFwLmdldChuYW1lKTsKICAgICAgICBpZiAocmVzdWx0ID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgIHJldHVybiByZXN1bHQuaW50VmFsdWUoKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQVRUUklCVVRFX0NPREUgPSAxMDA7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQVRUUklCVVRFX0dST1VQX0NPREUgPSAxMDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQU5ZX0FUVFJJQlVURV9DT0RFID0gMTAyOwoKICAgIHByaXZhdGUgc3RhdGljIENvZGVGb3JOYW1lRW50cnlbXSBhdHRyaWJ1dGVDb2RlcyA9IG5ldyBDb2RlRm9yTmFtZUVudHJ5W10KICAgIHsKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImF0dHJpYnV0ZSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBBVFRSSUJVVEVfQ09ERSksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhdHRyaWJ1dGVHcm91cCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBBVFRSSUJVVEVfR1JPVVBfQ09ERSksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhbnlBdHRyaWJ1dGUiLCAiaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiKSwgQU5ZX0FUVFJJQlVURV9DT0RFKSwKICAgIH07CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIGF0dHJpYnV0ZUNvZGVNYXAgPSBidWlsZEF0dHJpYnV0ZUNvZGVNYXAoKTsKCiAgICBwcml2YXRlIHN0YXRpYyBNYXAgYnVpbGRBdHRyaWJ1dGVDb2RlTWFwKCkKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGF0dHJpYnV0ZUNvZGVzLmxlbmd0aDsgaSsrKQogICAgICAgICAgICByZXN1bHQucHV0KGF0dHJpYnV0ZUNvZGVzW2ldLm5hbWUsICBuZXcgSW50ZWdlcihhdHRyaWJ1dGVDb2Rlc1tpXS5jb2RlKSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICBzdGF0aWMgaW50IHRyYW5zbGF0ZUF0dHJpYnV0ZUNvZGUoUU5hbWUgY3VycmVudE5hbWUpCiAgICB7CiAgICAgICAgSW50ZWdlciByZXN1bHQgPSAoSW50ZWdlcilhdHRyaWJ1dGVDb2RlTWFwLmdldChjdXJyZW50TmFtZSk7CiAgICAgICAgaWYgKHJlc3VsdCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICByZXR1cm4gcmVzdWx0LmludFZhbHVlKCk7CiAgICB9CgoKfQo=