LyoqCiAqICBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lIG9yIG1vcmUKICogIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiAgdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLgogKiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGUgdG8gWW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAKICogICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqICB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogKgogKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCgpwYWNrYWdlIG9yZy5hcGFjaGUuZ2Vyb25pbW8udHJhbnNhY3Rpb24ubWFuYWdlcjsKCmltcG9ydCBqYXZhLmlvLlByaW50V3JpdGVyOwppbXBvcnQgamF2YS5pby5TdHJpbmdXcml0ZXI7CmltcG9ydCBqYXZhLmlvLldyaXRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JZGVudGl0eUhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlua2VkTGlzdDsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CgppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uSGV1cmlzdGljTWl4ZWRFeGNlcHRpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi5IZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlJvbGxiYWNrRXhjZXB0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3RhdHVzOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3luY2hyb25pemF0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3lzdGVtRXhjZXB0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uVHJhbnNhY3Rpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi54YS5YQUV4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLnhhLlhBUmVzb3VyY2U7CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi54YS5YaWQ7CgppbXBvcnQgb3JnLnNsZjRqLkxvZ2dlcjsKaW1wb3J0IG9yZy5zbGY0ai5Mb2dnZXJGYWN0b3J5OwoKCi8qKgogKiBCYXNpYyBsb2NhbCB0cmFuc2FjdGlvbiB3aXRoIHN1cHBvcnQgZm9yIG11bHRpcGxlIHJlc291cmNlcy4KICoKICogQHZlcnNpb24gJFJldiQgJERhdGUkCiAqLwpwdWJsaWMgY2xhc3MgVHJhbnNhY3Rpb25JbXBsIGltcGxlbWVudHMgVHJhbnNhY3Rpb24gewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTG9nZ2VyIGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKCJUcmFuc2FjdGlvbiIpOwoKICAgIHByaXZhdGUgZmluYWwgWGlkRmFjdG9yeSB4aWRGYWN0b3J5OwogICAgcHJpdmF0ZSBmaW5hbCBYaWQgeGlkOwogICAgcHJpdmF0ZSBmaW5hbCBUcmFuc2FjdGlvbkxvZyB0eG5Mb2c7CiAgICBwcml2YXRlIGZpbmFsIGxvbmcgdGltZW91dDsKICAgIHByaXZhdGUgZmluYWwgTGlzdCBzeW5jTGlzdCA9IG5ldyBBcnJheUxpc3QoNSk7CiAgICBwcml2YXRlIGZpbmFsIExpc3QgaW50ZXJwb3NlZFN5bmNMaXN0ID0gbmV3IEFycmF5TGlzdCgzKTsKICAgIHByaXZhdGUgZmluYWwgTGlua2VkTGlzdCByZXNvdXJjZU1hbmFnZXJzID0gbmV3IExpbmtlZExpc3QoKTsKICAgIHByaXZhdGUgZmluYWwgSWRlbnRpdHlIYXNoTWFwIGFjdGl2ZVhhUmVzb3VyY2VzID0gbmV3IElkZW50aXR5SGFzaE1hcCgzKTsKICAgIHByaXZhdGUgZmluYWwgSWRlbnRpdHlIYXNoTWFwIHN1c3BlbmRlZFhhUmVzb3VyY2VzID0gbmV3IElkZW50aXR5SGFzaE1hcCgzKTsKICAgIHByaXZhdGUgaW50IHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICBwcml2YXRlIE9iamVjdCBsb2dNYXJrOwoKICAgIHByaXZhdGUgZmluYWwgTWFwIHJlc291cmNlcyA9IG5ldyBIYXNoTWFwKCk7CgogICAgVHJhbnNhY3Rpb25JbXBsKFhpZEZhY3RvcnkgeGlkRmFjdG9yeSwgVHJhbnNhY3Rpb25Mb2cgdHhuTG9nLCBsb25nIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdGhpcyh4aWRGYWN0b3J5LmNyZWF0ZVhpZCgpLCB4aWRGYWN0b3J5LCB0eG5Mb2csIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcyk7CiAgICB9CgogICAgVHJhbnNhY3Rpb25JbXBsKFhpZCB4aWQsIFhpZEZhY3RvcnkgeGlkRmFjdG9yeSwgVHJhbnNhY3Rpb25Mb2cgdHhuTG9nLCBsb25nIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdGhpcy54aWRGYWN0b3J5ID0geGlkRmFjdG9yeTsKICAgICAgICB0aGlzLnR4bkxvZyA9IHR4bkxvZzsKICAgICAgICB0aGlzLnhpZCA9IHhpZDsKICAgICAgICB0aGlzLnRpbWVvdXQgPSB0cmFuc2FjdGlvblRpbWVvdXRNaWxsaXNlY29uZHMgKyBUcmFuc2FjdGlvblRpbWVyLmdldEN1cnJlbnRUaW1lKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgdHhuTG9nLmJlZ2luKHhpZCk7CiAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgIFN5c3RlbUV4Y2VwdGlvbiBleCA9IG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGxvZ2dpbmcgYmVnaW47IHRyYW5zYWN0aW9uIG1hcmtlZCBmb3Igcm9sbCBiYWNrKSIpOwogICAgICAgICAgICBleC5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0FDVElWRTsKICAgIH0KCiAgICAvL3JlY29uc3RydWN0IGEgdHggZm9yIGFuIGV4dGVybmFsIHR4IGZvdW5kIGluIHJlY292ZXJ5CiAgICBwdWJsaWMgVHJhbnNhY3Rpb25JbXBsKFhpZCB4aWQsIFRyYW5zYWN0aW9uTG9nIHR4TG9nKSB7CiAgICAgICAgdGhpcy54aWRGYWN0b3J5ID0gbnVsbDsKICAgICAgICB0aGlzLnR4bkxvZyA9IHR4TG9nOwogICAgICAgIHRoaXMueGlkID0geGlkOwogICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSRUQ7CiAgICAgICAgLy9UT0RPIGlzIHRoaXMgYSBnb29kIGlkZWE/CiAgICAgICAgdGhpcy50aW1lb3V0ID0gTG9uZy5NQVhfVkFMVUU7CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCBpbnQgZ2V0U3RhdHVzKCkgewogICAgICAgIHJldHVybiBzdGF0dXM7CiAgICB9CgogICAgcHVibGljIE9iamVjdCBnZXRSZXNvdXJjZShPYmplY3Qga2V5KSB7CiAgICAgICAgcmV0dXJuIHJlc291cmNlcy5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRSb2xsYmFja09ubHkoKSB7CiAgICAgICAgcmV0dXJuIHN0YXR1cyA9PSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgIH0KCiAgICBwdWJsaWMgT2JqZWN0IGdldFRyYW5zYWN0aW9uS2V5KCkgewogICAgICAgIHJldHVybiB4aWQ7CiAgICB9CgogICAgcHVibGljIGludCBnZXRUcmFuc2FjdGlvblN0YXR1cygpIHsKICAgICAgICByZXR1cm4gc3RhdHVzOwogICAgfQoKICAgIHB1YmxpYyB2b2lkIHB1dFJlc291cmNlKE9iamVjdCBrZXksIE9iamVjdCB2YWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIllvdSBtdXN0IHN1cHBseSBhIG5vbi1udWxsIGtleSBmb3IgcHV0UmVzb3VyY2UiKTsKICAgICAgICB9CiAgICAgICAgcmVzb3VyY2VzLnB1dChrZXksIHZhbHVlKTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCByZWdpc3RlckludGVycG9zZWRTeW5jaHJvbml6YXRpb24oU3luY2hyb25pemF0aW9uIHN5bmNocm9uaXphdGlvbikgewogICAgICAgIGludGVycG9zZWRTeW5jTGlzdC5hZGQoc3luY2hyb25pemF0aW9uKTsKICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIHZvaWQgc2V0Um9sbGJhY2tPbmx5KCkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiB7CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s6CiAgICAgICAgICAgICAgICAvLyBub3RoaW5nIHRvIGRvCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIkNhbm5vdCBzZXQgcm9sbGJhY2sgb25seSwgc3RhdHVzIGlzICIgKyBnZXRTdGF0ZVN0cmluZyhzdGF0dXMpKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCB2b2lkIHJlZ2lzdGVyU3luY2hyb25pemF0aW9uKFN5bmNocm9uaXphdGlvbiBzeW5jaCkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiwgUm9sbGJhY2tFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgaWYgKHN5bmNoID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiU3luY2hyb25pemF0aW9uIGlzIG51bGwiKTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJUcmFuc2FjdGlvbiBpcyBtYXJrZWQgZm9yIHJvbGxiYWNrIik7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgIH0KICAgICAgICBzeW5jTGlzdC5hZGQoc3luY2gpOwogICAgfQoKICAgIHB1YmxpYyBzeW5jaHJvbml6ZWQgYm9vbGVhbiBlbmxpc3RSZXNvdXJjZShYQVJlc291cmNlIHhhUmVzKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBpZiAoeGFSZXMgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJYQVJlc291cmNlIGlzIG51bGwiKTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGFjdGl2ZVhhUmVzb3VyY2VzLmNvbnRhaW5zS2V5KHhhUmVzKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJ4YXJlc291cmNlOiAiICsgeGFSZXMgKyAiIGlzIGFscmVhZHkgZW5saXN0ZWQhIik7CiAgICAgICAgfQoKICAgICAgICB0cnkgewogICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSBzdXNwZW5kZWRYYVJlc291cmNlcy5yZW1vdmUoeGFSZXMpOwogICAgICAgICAgICBpZiAobWFuYWdlciAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICAvL3dlIGtub3cgYWJvdXQgdGhpcyBvbmUsIGl0IHdhcyBzdXNwZW5kZWQKICAgICAgICAgICAgICAgIHhhUmVzLnN0YXJ0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgWEFSZXNvdXJjZS5UTVJFU1VNRSk7CiAgICAgICAgICAgICAgICBhY3RpdmVYYVJlc291cmNlcy5wdXQoeGFSZXMsIG1hbmFnZXIpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy9pdCBpcyBub3Qgc3VzcGVuZGVkLgogICAgICAgICAgICBmb3IgKEl0ZXJhdG9yIGkgPSByZXNvdXJjZU1hbmFnZXJzLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7CiAgICAgICAgICAgICAgICBib29sZWFuIHNhbWVSTTsKICAgICAgICAgICAgICAgIC8vaWYgdGhlIHhhcmVzIGlzIGFscmVhZHkga25vd24sIHdlIG11c3QgYmUgcmVzdW1pbmcgYWZ0ZXIgYSBzdXNwZW5kLgogICAgICAgICAgICAgICAgaWYgKHhhUmVzID09IG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJ4YVJlcyAiICsgeGFSZXMgKyAiIGlzIGEgY29tbWl0dGVyIGJ1dCBpcyBub3QgYWN0aXZlIG9yIHN1c3BlbmRlZCIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy9PdGhlcndpc2UsIHNlZSBpZiB0aGlzIGlzIGEgbmV3IHhhcmVzIGZvciB0aGUgc2FtZSByZXNvdXJjZSBtYW5hZ2VyCiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHNhbWVSTSA9IHhhUmVzLmlzU2FtZVJNKG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkpOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKCJVbmV4cGVjdGVkIGVycm9yIGNoZWNraW5nIGZvciBzYW1lIFJNIiwgZSk7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoc2FtZVJNKSB7CiAgICAgICAgICAgICAgICAgICAgeGFSZXMuc3RhcnQobWFuYWdlci5nZXRCcmFuY2hJZCgpLCBYQVJlc291cmNlLlRNSk9JTik7CiAgICAgICAgICAgICAgICAgICAgYWN0aXZlWGFSZXNvdXJjZXMucHV0KHhhUmVzLCBtYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvL3dlIGtub3cgbm90aGluZyBhYm91dCB0aGlzIFhBUmVzb3VyY2Ugb3IgcmVzb3VyY2UgbWFuYWdlcgogICAgICAgICAgICBYaWQgYnJhbmNoSWQgPSB4aWRGYWN0b3J5LmNyZWF0ZUJyYW5jaCh4aWQsIHJlc291cmNlTWFuYWdlcnMuc2l6ZSgpICsgMSk7CiAgICAgICAgICAgIHhhUmVzLnN0YXJ0KGJyYW5jaElkLCBYQVJlc291cmNlLlRNTk9GTEFHUyk7CiAgICAgICAgICAgIGFjdGl2ZVhhUmVzb3VyY2VzLnB1dCh4YVJlcywgYWRkQnJhbmNoWGlkKHhhUmVzLCBicmFuY2hJZCkpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIGxvZy53YXJuKCJVbmFibGUgdG8gZW5saXN0IFhBUmVzb3VyY2UgIiArIHhhUmVzICsgIiwgZXJyb3JDb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICAvLyBtYXJrIHN0YXR1cyBhcyByb2xsYmFjayBvbmx5IGJlY2F1c2UgZW5saXN0IHJlc291cmNlIGZhaWxlZAogICAgICAgICAgICBzZXRSb2xsYmFja09ubHkoKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIGJvb2xlYW4gZGVsaXN0UmVzb3VyY2UoWEFSZXNvdXJjZSB4YVJlcywgaW50IGZsYWcpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCEoZmxhZyA9PSBYQVJlc291cmNlLlRNRkFJTCB8fCBmbGFnID09IFhBUmVzb3VyY2UuVE1TVUNDRVNTIHx8IGZsYWcgPT0gWEFSZXNvdXJjZS5UTVNVU1BFTkQpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oImludmFsaWQgZmxhZyBmb3IgZGVsaXN0UmVzb3VyY2U6ICIgKyBmbGFnKTsKICAgICAgICB9CiAgICAgICAgaWYgKHhhUmVzID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiWEFSZXNvdXJjZSBpcyBudWxsIik7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAoc3RhdHVzKSB7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgfQogICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGFjdGl2ZVhhUmVzb3VyY2VzLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgaWYgKG1hbmFnZXIgPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoZmxhZyA9PSBYQVJlc291cmNlLlRNU1VTUEVORCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigidHJ5aW5nIHRvIHN1c3BlbmQgYW4gaW5hY3RpdmUgeGFyZXNvdXJjZTogIiArIHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvL25vdCBhY3RpdmUsIGFuZCB3ZSBhcmUgbm90IHRyeWluZyB0byBzdXNwZW5kLiAgV2UgbXVzdCBiZSBlbmRpbmcgdHguCiAgICAgICAgICAgIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIHN1c3BlbmRlZFhhUmVzb3VyY2VzLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgICAgIGlmIChtYW5hZ2VyID09IG51bGwpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlJlc291cmNlIG5vdCBrbm93biB0byB0cmFuc2FjdGlvbjogIiArIHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgeGFSZXMuZW5kKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgZmxhZyk7CiAgICAgICAgICAgIGlmIChmbGFnID09IFhBUmVzb3VyY2UuVE1TVVNQRU5EKSB7CiAgICAgICAgICAgICAgICBzdXNwZW5kZWRYYVJlc291cmNlcy5wdXQoeGFSZXMsIG1hbmFnZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgbG9nLndhcm4oIlVuYWJsZSB0byBkZWxpc3QgWEFSZXNvdXJjZSAiICsgeGFSZXMgKyAiLCBlcnJvciBjb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8vVHJhbnNhY3Rpb24gbWV0aG9kLCBkb2VzIDJwYwogICAgcHVibGljIHZvaWQgY29tbWl0KCkgdGhyb3dzIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbiwgUm9sbGJhY2tFeGNlcHRpb24sIFNlY3VyaXR5RXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIGJlZm9yZVByZXBhcmUoKTsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiB0aW1lZG91dCA9IGZhbHNlOwogICAgICAgICAgICBpZiAoVHJhbnNhY3Rpb25UaW1lci5nZXRDdXJyZW50VGltZSgpID4gdGltZW91dCkgewogICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICB0aW1lZG91dCA9IHRydWU7CiAgICAgICAgICAgIH0gCgogICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLKSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlc0R1cmluZ0NvbW1pdChyZXNvdXJjZU1hbmFnZXJzLCBmYWxzZSk7CiAgICAgICAgICAgICAgICBpZiAodGltZWRvdXQpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlVuYWJsZSB0byBjb21taXQ6IFRyYW5zYWN0aW9uIHRpbWVvdXQiKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJVbmFibGUgdG8gY29tbWl0OiB0cmFuc2FjdGlvbiBtYXJrZWQgZm9yIHJvbGxiYWNrIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfQUNUSVZFKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBub3RoaW5nIHRvIGNvbW1pdAogICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBvbmUtcGhhc2UgY29tbWl0IGRlY2lzaW9uCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGFydCBwcmVwYXJlIHBhcnQgb2YgdHdvLXBoYXNlCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIHJlc291cmNlTWFuYWdlcnMgaXMgbm93IGltbXV0YWJsZQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBuby1waGFzZQogICAgICAgICAgICBpZiAocmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMCkgewogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIG9uZS1waGFzZQogICAgICAgICAgICBpZiAocmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMSkgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgcmVzb3VyY2VNYW5hZ2Vycy5nZXRGaXJzdCgpOwogICAgICAgICAgICAgICAgY29tbWl0UmVzb3VyY2UobWFuYWdlcik7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGJvb2xlYW4gd2lsbENvbW1pdCA9IGZhbHNlOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgLy8gdHdvLXBoYXNlCiAgICAgICAgICAgICAgICB3aWxsQ29tbWl0ID0gaW50ZXJuYWxQcmVwYXJlKCk7CiAgICAgICAgICAgIH0gY2F0Y2ggKFN5c3RlbUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhyZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICAgICAgICAgIHRocm93IGU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCgogICAgICAgICAgICAvLyBub3RpZnkgdGhlIFJNcwogICAgICAgICAgICBpZiAod2lsbENvbW1pdCkgewogICAgICAgICAgICAgICAgY29tbWl0UmVzb3VyY2VzKHJlc291cmNlTWFuYWdlcnMpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gc2V0IGV2ZXJSb2xsYmFjayB0byB0cnVlIGhlcmUgYmVjYXVzZSB0aGUgcm9sbGJhY2sgaGVyZSBpcyBjYXVzZWQgYnkgCiAgICAgICAgICAgICAgICAvLyBYQUV4Y2VwdGlvbiBkdXJpbmcgdGhlIGFib3ZlIGludGVybmFsUHJlcGFyZQogICAgICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXNEdXJpbmdDb21taXQocmVzb3VyY2VNYW5hZ2VycywgdHJ1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vVXNlZCBmcm9tIFhBVGVybWluYXRvciBmb3IgZmlyc3QgcGhhc2UgaW4gYSByZW1vdGVseSBjb250cm9sbGVkIHR4LgogICAgaW50IHByZXBhcmUoKSB0aHJvd3MgU3lzdGVtRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiB7CiAgICAgICAgYmVmb3JlUHJlcGFyZSgpOwogICAgICAgIGludCByZXN1bHQgPSBYQVJlc291cmNlLlhBX1JET05MWTsKICAgICAgICB0cnkgewogICAgICAgICAgICBMaW5rZWRMaXN0IHJtczsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfQUNUSVZFKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc291cmNlTWFuYWdlcnMuc2l6ZSgpID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyB0byBjb21taXQKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgcHJlcGFyZSBwYXJ0IG9mIHR3by1waGFzZQogICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyByZXNvdXJjZU1hbmFnZXJzIGlzIG5vdyBpbW11dGFibGUKICAgICAgICAgICAgICAgIHJtcyA9IHJlc291cmNlTWFuYWdlcnM7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGJvb2xlYW4gd2lsbENvbW1pdCA9IGludGVybmFsUHJlcGFyZSgpOwoKICAgICAgICAgICAgLy8gbm90aWZ5IHRoZSBSTXMKICAgICAgICAgICAgaWYgKHdpbGxDb21taXQpIHsKICAgICAgICAgICAgICAgIGlmICghcm1zLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFhBUmVzb3VyY2UuWEFfT0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhybXMpOwogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJVbmFibGUgdG8gY29tbWl0Iik7CiAgICAgICAgICAgIH0KICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09IFhBUmVzb3VyY2UuWEFfUkRPTkxZKSB7CiAgICAgICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICAvL3VzZWQgZnJvbSBYQVRlcm1pbmF0b3IgZm9yIGNvbW1pdCBwaGFzZSBvZiBub24tcmVhZG9ubHkgcmVtb3RlbHkgY29udHJvbGxlZCB0eC4KICAgIHZvaWQgcHJlcGFyZWRDb21taXQoKSB0aHJvd3MgSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24sIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbW1pdFJlc291cmNlcyhyZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vaGVscGVyIG1ldGhvZCB1c2VkIGJ5IFRyYW5zYWN0aW9uLmNvbW1pdCBhbmQgWEFUZXJtaW5hdG9yIHByZXBhcmUuCiAgICBwcml2YXRlIHZvaWQgYmVmb3JlUHJlcGFyZSgpIHsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBiZWZvcmVDb21wbGV0aW9uKCk7CiAgICAgICAgZW5kUmVzb3VyY2VzKCk7CiAgICB9CgoKICAgIC8vaGVscGVyIG1ldGhvZCB1c2VkIGJ5IFRyYW5zYWN0aW9uLmNvbW1pdCBhbmQgWEFUZXJtaW5hdG9yIHByZXBhcmUuCiAgICBwcml2YXRlIGJvb2xlYW4gaW50ZXJuYWxQcmVwYXJlKCkgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CgogICAgICAgIGZvciAoSXRlcmF0b3Igcm1zID0gcmVzb3VyY2VNYW5hZ2Vycy5pdGVyYXRvcigpOyBybXMuaGFzTmV4dCgpOykgewogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgIT0gU3RhdHVzLlNUQVRVU19QUkVQQVJJTkcpIHsKICAgICAgICAgICAgICAgICAgICAvLyB3ZSB3ZXJlIG1hcmtlZCBmb3Igcm9sbGJhY2sKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSBybXMubmV4dCgpOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgaW50IHZvdGUgPSBtYW5hZ2VyLmdldENvbW1pdHRlcigpLnByZXBhcmUobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgIGlmICh2b3RlID09IFhBUmVzb3VyY2UuWEFfUkRPTkxZKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gd2UgZG9uJ3QgbmVlZCB0byBjb25zaWRlciB0aGlzIFJNIGFueSBtb3JlCiAgICAgICAgICAgICAgICAgICAgcm1zLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9STUVSUiAKICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9QUk9UTwogICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX0lOVkFMKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHByZXBhcmU7IHRyYW5zYWN0aW9uIHdhcyByb2xsZWQgYmFjayIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgICAgIC8qIFBlciBKVEEgc3BlYywgIElmIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHdhbnRzIHRvIHJvbGwgYmFjayB0aGUgdHJhbnNhY3Rpb24sIAogICAgICAgICAgICAgICAgICAgIGl0IHNob3VsZCBkbyBzbyBieSB0aHJvd2luZyBhbiBhcHByb3ByaWF0ZSBYQUV4Y2VwdGlvbiBpbiB0aGUgcHJlcGFyZSBtZXRob2QuCiAgICAgICAgICAgICAgICAgICAgQWxzbyBwZXIgT1RTIHNwZWM6CiAgICAgICAgICAgICAgICAgICAgVGhlIHJlc291cmNlIGNhbiByZXR1cm4gVm90ZVJvbGxiYWNrIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLCBpbmNsdWRpbmcgbm90IGhhdmluZyAKICAgICAgICAgICAgICAgICAgICBhbnkga25vd2xlZGdlIGFib3V0IHRoZSB0cmFuc2FjdGlvbiAod2hpY2ggbWlnaHQgaGFwcGVuIGFmdGVyIGEgY3Jhc2gpLiBJZiB0aGlzIAogICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlIGlzIHJldHVybmVkLCB0aGUgdHJhbnNhY3Rpb24gbXVzdCBiZSByb2xsZWQgYmFjay4gRnVydGhlcm1vcmUsIHRoZSBUcmFuc2FjdGlvbiAKICAgICAgICAgICAgICAgICAgICBTZXJ2aWNlIGlzIG5vdCByZXF1aXJlZCB0byBwZXJmb3JtIGFueSBhZGRpdGlvbmFsIG9wZXJhdGlvbnMgb24gdGhpcyByZXNvdXJjZS4qLwogICAgICAgICAgICAgICAgICAgIC8vcm1zLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBkZWNpc2lvbiB0aW1lLi4uCiAgICAgICAgYm9vbGVhbiB3aWxsQ29tbWl0OwogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICB3aWxsQ29tbWl0ID0gKHN0YXR1cyAhPSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSyk7CiAgICAgICAgICAgIGlmICh3aWxsQ29tbWl0KSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1BSRVBBUkVEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vIGxvZyBvdXIgZGVjaXNpb24KICAgICAgICBpZiAod2lsbENvbW1pdCAmJiAhcmVzb3VyY2VNYW5hZ2Vycy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIGxvZ01hcmsgPSB0eG5Mb2cucHJlcGFyZSh4aWQsIHJlc291cmNlTWFuYWdlcnMpOwogICAgICAgICAgICB9IGNhdGNoIChMb2dFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhyZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBzZSkgewogICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVW5hYmxlIHRvIHJvbGxiYWNrIGFmdGVyIGZhaWx1cmUgdG8gbG9nIHByZXBhcmUiLCBzZS5nZXRDYXVzZSgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGxvZ2dpbmcgcHJlcGFyZTsgdHJhbnNhY3Rpb24gd2FzIHJvbGxlZCBiYWNrKSIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gd2lsbENvbW1pdDsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCByb2xsYmFjaygpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgTGlzdCBybXM7CiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN3aXRjaCAoc3RhdHVzKSB7CiAgICAgICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzoKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiU3RhdHVzIGlzICIgKyBnZXRTdGF0ZVN0cmluZyhzdGF0dXMpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBybXMgPSByZXNvdXJjZU1hbmFnZXJzOwogICAgICAgIH0KCiAgICAgICAgZW5kUmVzb3VyY2VzKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXMocm1zKTsKICAgICAgICAgICAgLy9vbmx5IHdyaXRlIHJvbGxiYWNrIHJlY29yZCBpZiB3ZSBoYXZlIGFscmVhZHkgd3JpdHRlbiBwcmVwYXJlIHJlY29yZC4KICAgICAgICAgICAgaWYgKGxvZ01hcmsgIT0gbnVsbCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICB0eG5Mb2cucm9sbGJhY2soeGlkLCBsb2dNYXJrKTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKExvZ0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXMocm1zKTsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gc2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJVbmFibGUgdG8gcm9sbGJhY2sgYWZ0ZXIgZmFpbHVyZSB0byBsb2cgZGVjaXNpb24iLCBzZS5nZXRDYXVzZSgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgbG9nZ2luZyByb2xsYmFjayIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGFmdGVyQ29tcGxldGlvbigpOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGJlZm9yZUNvbXBsZXRpb24oKSB7CiAgICAgICAgYmVmb3JlQ29tcGxldGlvbihzeW5jTGlzdCk7CiAgICAgICAgYmVmb3JlQ29tcGxldGlvbihpbnRlcnBvc2VkU3luY0xpc3QpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCBiZWZvcmVDb21wbGV0aW9uKExpc3Qgc3luY3MpIHsKICAgICAgICBpbnQgaSA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgU3luY2hyb25pemF0aW9uIHN5bmNoOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIGlmIChpID09IHN5bmNzLnNpemUoKSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgc3luY2ggPSAoU3luY2hyb25pemF0aW9uKSBzeW5jcy5nZXQoaSsrKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgc3luY2guYmVmb3JlQ29tcGxldGlvbigpOwogICAgICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgbG9nLndhcm4oIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGZyb20gYmVmb3JlQ29tcGxldGlvbjsgdHJhbnNhY3Rpb24gd2lsbCByb2xsIGJhY2siLCBlKTsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCBhZnRlckNvbXBsZXRpb24oKSB7CiAgICAgICAgLy8gdGhpcyBkb2VzIG5vdCBzeW5jaHJvbml6ZSBiZWNhdXNlIG5vdGhpbmcgY2FuIG1vZGlmeSBvdXIgc3RhdGUgYXQgdGhpcyB0aW1lCiAgICAgICAgYWZ0ZXJDb21wbGV0aW9uKGludGVycG9zZWRTeW5jTGlzdCk7CiAgICAgICAgYWZ0ZXJDb21wbGV0aW9uKHN5bmNMaXN0KTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgYWZ0ZXJDb21wbGV0aW9uKExpc3Qgc3luY3MpIHsKICAgICAgICBmb3IgKEl0ZXJhdG9yIGkgPSBzeW5jcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKICAgICAgICAgICAgU3luY2hyb25pemF0aW9uIHN5bmNoID0gKFN5bmNocm9uaXphdGlvbikgaS5uZXh0KCk7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBzeW5jaC5hZnRlckNvbXBsZXRpb24oc3RhdHVzKTsKICAgICAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIGxvZy53YXJuKCJVbmV4cGVjdGVkIGV4Y2VwdGlvbiBmcm9tIGFmdGVyQ29tcGxldGlvbjsgY29udGludWluZyIsIGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCBlbmRSZXNvdXJjZXMoKSB7CiAgICAgICAgZW5kUmVzb3VyY2VzKGFjdGl2ZVhhUmVzb3VyY2VzKTsKICAgICAgICBlbmRSZXNvdXJjZXMoc3VzcGVuZGVkWGFSZXNvdXJjZXMpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCBlbmRSZXNvdXJjZXMoSWRlbnRpdHlIYXNoTWFwIHJlc291cmNlTWFwKSB7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgWEFSZXNvdXJjZSB4YVJlczsKICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlcjsKICAgICAgICAgICAgaW50IGZsYWdzOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIFNldCBlbnRyeVNldCA9IHJlc291cmNlTWFwLmVudHJ5U2V0KCk7CiAgICAgICAgICAgICAgICBpZiAoZW50cnlTZXQuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgTWFwLkVudHJ5IGVudHJ5ID0gKE1hcC5FbnRyeSkgZW50cnlTZXQuaXRlcmF0b3IoKS5uZXh0KCk7CiAgICAgICAgICAgICAgICB4YVJlcyA9IChYQVJlc291cmNlKSBlbnRyeS5nZXRLZXkoKTsKICAgICAgICAgICAgICAgIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGVudHJ5LmdldFZhbHVlKCk7CiAgICAgICAgICAgICAgICBmbGFncyA9IChzdGF0dXMgPT0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0spID8gWEFSZXNvdXJjZS5UTUZBSUwgOiBYQVJlc291cmNlLlRNU1VDQ0VTUzsKICAgICAgICAgICAgICAgIHJlc291cmNlTWFwLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHhhUmVzLmVuZChtYW5hZ2VyLmdldEJyYW5jaElkKCksIGZsYWdzKTsKICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgbG9nLndhcm4oIkVycm9yIGVuZGluZyBhc3NvY2lhdGlvbiBmb3IgWEFSZXNvdXJjZSAiICsgeGFSZXMgKyAiOyB0cmFuc2FjdGlvbiB3aWxsIHJvbGwgYmFjay4gWEEgZXJyb3IgY29kZTogIiArIGUuZXJyb3JDb2RlLCBlKTsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCByb2xsYmFja1Jlc291cmNlcyhMaXN0IHJtcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgU3lzdGVtRXhjZXB0aW9uIGNhdXNlID0gbnVsbDsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJtcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKICAgICAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGkubmV4dCgpOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLnJvbGxiYWNrKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJVbmV4cGVjdGVkIGV4Y2VwdGlvbiByb2xsaW5nIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCBzZXQgdGhlIGNhdXNlIGhlcmUKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgcm9sbGVkIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRkFJTCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3Qgc2V0IHRoZSBjYXVzZSBoZXJlIGJlY2F1c2Ugd2UgZXhwZWN0IHRoZSB0cmFuc2FjdGlvbiB0byBiZSByb2xsZWQgYmFjayBldmVudHVhbGx5CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZvciBSTUZBSUwsIGl0IG1lYW5zIHJlc291cmNlIHVuYXZhaWxhYmxlIHRlbXBvcmFyaWx5LiAgCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvIHdlIG5lZWQga2VlcCBzZW5kaW5nIHJlcXVlc3QgdG8gcmVzb3VyY2UgdG8gbWFrZSBzdXJlIHRoZSByb2xsIGJhY2sgY29tcGxldGVzPwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IG5ldyBTeXN0ZW1FeGNlcHRpb24oZS5lcnJvckNvZGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHJvbGxpbmcgYmFjayIpLmluaXRDYXVzZShlKTsgICAgICAgICAgICAKICAgICAgICB9ICAgICAgICAgICAgCgogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s7CiAgICAgICAgfQogICAgICAgIGlmIChjYXVzZSAhPSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IGNhdXNlOwogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHZvaWQgcm9sbGJhY2tSZXNvdXJjZXNEdXJpbmdDb21taXQoTGlzdCBybXMsIGJvb2xlYW4gZXZlclJiKSB0aHJvd3MgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24sIFJvbGxiYWNrRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIFhBRXhjZXB0aW9uIGNhdXNlID0gbnVsbDsKICAgICAgICBib29sZWFuIGV2ZXJSb2xsZWRiYWNrID0gZXZlclJiOwogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExJTkdfQkFDSzsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBpID0gcm1zLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkucm9sbGJhY2sobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICBldmVyUm9sbGVkYmFjayA9IHRydWU7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQikgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3Qgc2V0IHRoZSBjYXVzZSBoZXJlIGFzIHRoZSByZXN1bHRpbmcgYmVoYXZpb3IgaXMgc2FtZSBhcyByZXF1ZXN0ZWQgYmVoYXZpb3IKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiBoZXVyaXN0aWNhbGx5IHJvbGxlZCBiYWNrICIgKyBtYW5hZ2VyLmdldENvbW1pdHRlcigpICsgIjsgY29udGludWluZyB3aXRoIHJvbGxiYWNrIiwgZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZXJSb2xsZWRiYWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJNSVgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiBoZXVyaXN0aWNhbGx5IGNvbW1pdHRlZCBhbmQgcm9sbGVkIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgICAgICBldmVyUm9sbGVkYmFjayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSQ09NKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSBjb21taXR0ZWQgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfUkJST0xMQkFDSyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfTk9UQQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9STUZBSUwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gWEFFeGNlcHRpb24uWEFfUkJST0xMQkFDSyBkdXJpbmcgY29tbWl0L3JvbGxiYWNrLCB0aHVzIFJvbGxiYWNrRXhjZXB0aW9uIGlzIGV4cGVjdGVkCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgbWVhbnMgdHJhbnNhY3Rpb24gYnJhbmNoIGVycm9yIGFuZCB0cmFuc2FjdGlvbiBoYXMgYmVlbiByb2xsZWQgYmFjawogICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3Qgc2V0IHRoZSBjYXVzZSBoZXJlIGJlY2F1c2Ugd2UgZXhwZWN0IHRoZSB0cmFuc2FjdGlvbiB0byBiZSByb2xsZWQgYmFjayBldmVudHVhbGx5CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZvciBSTUZBSUwsIGl0IG1lYW5zIHJlc291cmNlIHVuYXZhaWxhYmxlIHRlbXBvcmFyaWx5LiAgCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvIHdlIG5lZWQga2VlcCBzZW5kaW5nIHJlcXVlc3QgdG8gcmVzb3VyY2UgdG8gbWFrZSBzdXJlIHRoZSByb2xsIGJhY2sgY29tcGxldGVzPwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJTeXN0ZW0gZXJyb3IgZHVyaW5nIGNvbW1pdC9yb2xsaW5nIGJhY2siKS5pbml0Q2F1c2UoZSk7ICAgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIAogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGlmIChjYXVzZSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IChSb2xsYmFja0V4Y2VwdGlvbikgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJVbmFibGUgdG8gY29tbWl0OiB0cmFuc2FjdGlvbiBtYXJrZWQgZm9yIHJvbGxiYWNrIikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJDT00gJiYgZXZlclJvbGxlZGJhY2spIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbikgbmV3IEhldXJpc3RpY01peGVkRXhjZXB0aW9uKCJIZXVyaXN0aWNNaXhlZCBlcnJvciBkdXJpbmcgY29tbWl0L3JvbGxpbmcgYmFjayIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJNSVgpIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbikgbmV3IEhldXJpc3RpY01peGVkRXhjZXB0aW9uKCJIZXVyaXN0aWNNaXhlZCBlcnJvciBkdXJpbmcgY29tbWl0L3JvbGxpbmcgYmFjayIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJTeXN0ZW0gRXJyb3IgZHVyaW5nIGNvbW1pdC9yb2xsaW5nIGJhY2siKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IAogICAgICAgIH0KICAgIH0KICAgIAogICAgcHJpdmF0ZSB2b2lkIGNvbW1pdFJlc291cmNlKFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIpIHRocm93cyBSb2xsYmFja0V4Y2VwdGlvbiwgSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24sIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb257CiAgICAgICAgWEFFeGNlcHRpb24gY2F1c2UgPSBudWxsOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIHRyeSB7CgogICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5jb21taXQobWFuYWdlci5nZXRCcmFuY2hJZCgpLCB0cnVlKTsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVEVEOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICAvL3Rocm93IChIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbikgbmV3IEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgb25lLXBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbikgbmV3IEhldXJpc3RpY01peGVkRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgb25lLXBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUkNPTSkgewogICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCB0aHJvdyBhbiBleGNlcHRpb24gYXMgdGhlIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGNvbW1pdHRlZAogICAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiBoZXVyaXN0aWNhbGx5IGNvbW1pdHRlZCIpOwogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgCiAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgCiAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfTk9UQSkgewogICAgICAgICAgICAgICAgICAgIC8vIFBlciBYQSBzcGVjLCBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIGZyb20gY29tbWl0IG1lYW5zIEFuIGVycm9yIG9jY3VycmVkIGluIAogICAgICAgICAgICAgICAgICAgIC8vIGNvbW1pdHRpbmcgdGhlIHdvcmsgcGVyZm9ybWVkIG9uIGJlaGFsZiBvZiB0aGUgdHJhbnNhY3Rpb24gYnJhbmNoIAogICAgICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgYnJhbmNo1XMgd29yayBoYXMgYmVlbiByb2xsZWQgYmFjay4gCiAgICAgICAgICAgICAgICAgICAgLy8gWEFFeGNlcHRpb24uWEFFUl9OT1RBOiAgc3N1bWUgdGhlIERCIHRvb2sgYSB1bmlsYXRlcmFsIHJvbGxiYWNrIGRlY2lzaW9uIGFuZCBmb3Jnb3QgdGhlIHRyYW5zYWN0aW9uCiAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIHJvbGxlZCBiYWNrIik7CiAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIC8vIHRocm93IChSb2xsYmFja0V4Y2VwdGlvbikgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgb25lLXBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShlKTsgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIC8vdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIG9uZS1waGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfTk9UQSkgewogICAgICAgICAgICAgICAgLy8gTk9UQSBpbiByZXNwb25zZSB0byBmb3JnZXQsIG1lYW5zIHRoZSByZXNvdXJjZSBhbHJlYWR5IGZvcmdvdCB0aGUgdHJhbnNhY3Rpb24KICAgICAgICAgICAgICAgIC8vIGlnbm9yZQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIG9uZSBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYgKGNhdXNlICE9IG51bGwpIHsKICAgICAgICAgICAgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbikgbmV3IEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJNSVgpIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbikgbmV3IEhldXJpc3RpY01peGVkRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgCiAgICAgICAgICAgICAgICAgICAgfHwgY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgCiAgICAgICAgICAgICAgICAgICAgfHwgY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfTk9UQSkgewogICAgICAgICAgICAgICAgdGhyb3cgKFJvbGxiYWNrRXhjZXB0aW9uKSBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSAKICAgICAgICB9CiAgICB9CiAgICAKICAgIHByaXZhdGUgdm9pZCBjb21taXRSZXNvdXJjZXMoTGlzdCBybXMpIHRocm93cyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbiwgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgWEFFeGNlcHRpb24gY2F1c2UgPSBudWxsOwogICAgICAgIGJvb2xlYW4gZXZlcmNvbW1pdCA9IGZhbHNlOwogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRJTkc7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJtcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKICAgICAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGkubmV4dCgpOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmNvbW1pdChtYW5hZ2VyLmdldEJyYW5jaElkKCksIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICBldmVyY29tbWl0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGNvbW1pdHRpbmcgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHRvIGNvbW1pdCBvdGhlciBSTXMiLCBlKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiBoZXVyaXN0aWNhbGx5IHJvbGxlZCBiYWNrIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJNSVgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIGFuZCByb2xsZWQgYmFjayIpOwogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZXJjb21taXQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUkNPTSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3QgdGhyb3cgYW4gZXhjZXB0aW9uIGFzIHRoZSB0cmFuc2FjdGlvbiBoYXMgYmVlbiBjb21taXR0ZWQKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZXJjb21taXQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEpIHsKICAgICAgICAgICAgICAgIC8vIE5PVEEgaW4gcmVzcG9uc2UgdG8gZm9yZ2V0LCBtZWFucyB0aGUgcmVzb3VyY2UgYWxyZWFkeSBmb3Jnb3QgdGhlIHRyYW5zYWN0aW9uCiAgICAgICAgICAgICAgICAvLyBpZ25vcmUKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vaWYgYWxsIHJlc291cmNlcyB3ZXJlIHJlYWQgb25seSwgd2UgZGlkbid0IHdyaXRlIGEgcHJlcGFyZSByZWNvcmQuCiAgICAgICAgaWYgKCFybXMuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICB0eG5Mb2cuY29tbWl0KHhpZCwgbG9nTWFyayk7CiAgICAgICAgICAgIH0gY2F0Y2ggKExvZ0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGxvZ2dpbmcgY29tbWl0IGNvbXBsZXRpb24gZm9yIHhpZCAiICsgeGlkLCBlKTsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIlVuZXhwZWN0ZWQgZXJyb3IgbG9nZ2luZyBjb21taXQgY29tcGxldGlvbiBmb3IgeGlkICIgKyB4aWQpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgfQogICAgICAgIGlmIChjYXVzZSAhPSBudWxsKSB7CiAgICAgICAgICAgIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCICYmICFldmVyY29tbWl0KSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIgJiYgZXZlcmNvbW1pdCkgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSAKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGdldFN0YXRlU3RyaW5nKGludCBzdGF0dXMpIHsKICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfQUNUSVZFIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1BSRVBBUklORyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19QUkVQQVJFRDoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1BSRVBBUkVEIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX01BUktFRF9ST0xMQkFDSyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19ST0xMSU5HX0JBQ0siOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX0NPTU1JVFRJTkciOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQ09NTUlUVEVEOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfQ09NTUlUVEVEIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19ST0xMRURCQUNLIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfTk9fVFJBTlNBQ1RJT04iOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfVU5LTk9XTjoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1VOS05PV04iOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKCk7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhPYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIFRyYW5zYWN0aW9uSW1wbCkgewogICAgICAgICAgICBUcmFuc2FjdGlvbkltcGwgb3RoZXIgPSAoVHJhbnNhY3Rpb25JbXBsKSBvYmo7CiAgICAgICAgICAgIHJldHVybiB4aWQuZXF1YWxzKG90aGVyLnhpZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KCiAgICAvL3doZW4gdXNlZCBmcm9tIHJlY292ZXJ5LCBkbyBub3QgYWRkIG1hbmFnZXIgdG8gYWN0aXZlIG9yIHN1c3BlbmRlZCByZXNvdXJjZSBtYXBzLgogICAgLy8gVGhlIHhhcmVzb3VyY2VzIGhhdmUgYWxyZWFkeSBiZWVuIGVuZGVkIHdpdGggVE1TVUNDRVNTLgogICAgcHVibGljIFRyYW5zYWN0aW9uQnJhbmNoIGFkZEJyYW5jaFhpZChYQVJlc291cmNlIHhhUmVzLCBYaWQgYnJhbmNoSWQpIHsKICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gbmV3IFRyYW5zYWN0aW9uQnJhbmNoKHhhUmVzLCBicmFuY2hJZCk7CiAgICAgICAgcmVzb3VyY2VNYW5hZ2Vycy5hZGQobWFuYWdlcik7CiAgICAgICAgcmV0dXJuIG1hbmFnZXI7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgY2xhc3MgVHJhbnNhY3Rpb25CcmFuY2ggaW1wbGVtZW50cyBUcmFuc2FjdGlvbkJyYW5jaEluZm8gewogICAgICAgIHByaXZhdGUgZmluYWwgWEFSZXNvdXJjZSBjb21taXR0ZXI7CiAgICAgICAgcHJpdmF0ZSBmaW5hbCBYaWQgYnJhbmNoSWQ7CgogICAgICAgIHB1YmxpYyBUcmFuc2FjdGlvbkJyYW5jaChYQVJlc291cmNlIHhhUmVzLCBYaWQgYnJhbmNoSWQpIHsKICAgICAgICAgICAgY29tbWl0dGVyID0geGFSZXM7CiAgICAgICAgICAgIHRoaXMuYnJhbmNoSWQgPSBicmFuY2hJZDsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBYQVJlc291cmNlIGdldENvbW1pdHRlcigpIHsKICAgICAgICAgICAgcmV0dXJuIGNvbW1pdHRlcjsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBYaWQgZ2V0QnJhbmNoSWQoKSB7CiAgICAgICAgICAgIHJldHVybiBicmFuY2hJZDsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBTdHJpbmcgZ2V0UmVzb3VyY2VOYW1lKCkgewogICAgICAgICAgICBpZiAoY29tbWl0dGVyIGluc3RhbmNlb2YgTmFtZWRYQVJlc291cmNlKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gKChOYW1lZFhBUmVzb3VyY2UpIGNvbW1pdHRlcikuZ2V0TmFtZSgpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gaWYgaXQgaXNuJ3QgYSBuYW1lZCByZXNvdXJjZSBzaG91bGQgd2UgcmVhbGx5IHN0b3AgYWxsIHByb2Nlc3NpbmcgaGVyZSEKICAgICAgICAgICAgICAgIC8vIE1heWJlIHRoaXMgd291bGQgYmUgYmV0dGVyIHRvIGhhbmRsZSBlbHNlIHdoZXJlIGFuZCBkbyB3ZSByZWFsbHkgd2FudCB0byBwcmV2ZW50IGFsbCBwcm9jZXNzaW5nIG9mIHRyYW5zYWN0aW9ucz8KICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiUGxlYXNlIGNvcnJlY3QgdGhlIGludGVncmF0aW9uIGFuZCBzdXBwbHkgYSBOYW1lZFhBUmVzb3VyY2UiLCBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJDYW5ub3QgbG9nIHRyYW5zYWN0aW9ucyBhcyAiICsgY29tbWl0dGVyICsgIiBpcyBub3QgYSBOYW1lZFhBUmVzb3VyY2UuIikpOwogICAgICAgICAgICAgICAgcmV0dXJuIGNvbW1pdHRlci50b1N0cmluZygpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgWGlkIGdldEJyYW5jaFhpZCgpIHsKICAgICAgICAgICAgcmV0dXJuIGJyYW5jaElkOwogICAgICAgIH0KICAgIH0KCgp9Cg==