LyoqCiAqICBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lIG9yIG1vcmUKICogIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiAgdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLgogKiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGUgdG8gWW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAKICogICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqICB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogKgogKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCgpwYWNrYWdlIG9yZy5hcGFjaGUuZ2Vyb25pbW8udHJhbnNhY3Rpb24ubWFuYWdlcjsKCmltcG9ydCBqYXZhLmlvLlByaW50V3JpdGVyOwppbXBvcnQgamF2YS5pby5TdHJpbmdXcml0ZXI7CmltcG9ydCBqYXZhLmlvLldyaXRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JZGVudGl0eUhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlua2VkTGlzdDsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CgppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uSGV1cmlzdGljTWl4ZWRFeGNlcHRpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi5IZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlJvbGxiYWNrRXhjZXB0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3RhdHVzOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3luY2hyb25pemF0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uU3lzdGVtRXhjZXB0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uVHJhbnNhY3Rpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi54YS5YQUV4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLnhhLlhBUmVzb3VyY2U7CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi54YS5YaWQ7CgppbXBvcnQgb3JnLnNsZjRqLkxvZ2dlcjsKaW1wb3J0IG9yZy5zbGY0ai5Mb2dnZXJGYWN0b3J5OwoKCi8qKgogKiBCYXNpYyBsb2NhbCB0cmFuc2FjdGlvbiB3aXRoIHN1cHBvcnQgZm9yIG11bHRpcGxlIHJlc291cmNlcy4KICoKICogQHZlcnNpb24gJFJldiQgJERhdGUkCiAqLwpwdWJsaWMgY2xhc3MgVHJhbnNhY3Rpb25JbXBsIGltcGxlbWVudHMgVHJhbnNhY3Rpb24gewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTG9nZ2VyIGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKCJUcmFuc2FjdGlvbiIpOwoKICAgIHByaXZhdGUgZmluYWwgWGlkRmFjdG9yeSB4aWRGYWN0b3J5OwogICAgcHJpdmF0ZSBmaW5hbCBYaWQgeGlkOwogICAgcHJpdmF0ZSBmaW5hbCBUcmFuc2FjdGlvbkxvZyB0eG5Mb2c7CiAgICBwcml2YXRlIGZpbmFsIGxvbmcgdGltZW91dDsKICAgIHByaXZhdGUgZmluYWwgTGlzdCBzeW5jTGlzdCA9IG5ldyBBcnJheUxpc3QoNSk7CiAgICBwcml2YXRlIGZpbmFsIExpc3QgaW50ZXJwb3NlZFN5bmNMaXN0ID0gbmV3IEFycmF5TGlzdCgzKTsKICAgIHByaXZhdGUgZmluYWwgTGlua2VkTGlzdCByZXNvdXJjZU1hbmFnZXJzID0gbmV3IExpbmtlZExpc3QoKTsKICAgIHByaXZhdGUgZmluYWwgSWRlbnRpdHlIYXNoTWFwIGFjdGl2ZVhhUmVzb3VyY2VzID0gbmV3IElkZW50aXR5SGFzaE1hcCgzKTsKICAgIHByaXZhdGUgZmluYWwgSWRlbnRpdHlIYXNoTWFwIHN1c3BlbmRlZFhhUmVzb3VyY2VzID0gbmV3IElkZW50aXR5SGFzaE1hcCgzKTsKICAgIHByaXZhdGUgaW50IHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICBwcml2YXRlIE9iamVjdCBsb2dNYXJrOwoKICAgIHByaXZhdGUgZmluYWwgTWFwIHJlc291cmNlcyA9IG5ldyBIYXNoTWFwKCk7CgogICAgVHJhbnNhY3Rpb25JbXBsKFhpZEZhY3RvcnkgeGlkRmFjdG9yeSwgVHJhbnNhY3Rpb25Mb2cgdHhuTG9nLCBsb25nIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdGhpcyh4aWRGYWN0b3J5LmNyZWF0ZVhpZCgpLCB4aWRGYWN0b3J5LCB0eG5Mb2csIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcyk7CiAgICB9CgogICAgVHJhbnNhY3Rpb25JbXBsKFhpZCB4aWQsIFhpZEZhY3RvcnkgeGlkRmFjdG9yeSwgVHJhbnNhY3Rpb25Mb2cgdHhuTG9nLCBsb25nIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdGhpcy54aWRGYWN0b3J5ID0geGlkRmFjdG9yeTsKICAgICAgICB0aGlzLnR4bkxvZyA9IHR4bkxvZzsKICAgICAgICB0aGlzLnhpZCA9IHhpZDsKICAgICAgICB0aGlzLnRpbWVvdXQgPSB0cmFuc2FjdGlvblRpbWVvdXRNaWxsaXNlY29uZHMgKyBUcmFuc2FjdGlvblRpbWVyLmdldEN1cnJlbnRUaW1lKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgdHhuTG9nLmJlZ2luKHhpZCk7CiAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgIFN5c3RlbUV4Y2VwdGlvbiBleCA9IG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGxvZ2dpbmcgYmVnaW47IHRyYW5zYWN0aW9uIG1hcmtlZCBmb3Igcm9sbCBiYWNrKSIpOwogICAgICAgICAgICBleC5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0FDVElWRTsKICAgIH0KCiAgICAvL3JlY29uc3RydWN0IGEgdHggZm9yIGFuIGV4dGVybmFsIHR4IGZvdW5kIGluIHJlY292ZXJ5CiAgICBwdWJsaWMgVHJhbnNhY3Rpb25JbXBsKFhpZCB4aWQsIFRyYW5zYWN0aW9uTG9nIHR4TG9nKSB7CiAgICAgICAgdGhpcy54aWRGYWN0b3J5ID0gbnVsbDsKICAgICAgICB0aGlzLnR4bkxvZyA9IHR4TG9nOwogICAgICAgIHRoaXMueGlkID0geGlkOwogICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSRUQ7CiAgICAgICAgLy9UT0RPIGlzIHRoaXMgYSBnb29kIGlkZWE/CiAgICAgICAgdGhpcy50aW1lb3V0ID0gTG9uZy5NQVhfVkFMVUU7CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCBpbnQgZ2V0U3RhdHVzKCkgewogICAgICAgIHJldHVybiBzdGF0dXM7CiAgICB9CgogICAgcHVibGljIE9iamVjdCBnZXRSZXNvdXJjZShPYmplY3Qga2V5KSB7CiAgICAgICAgcmV0dXJuIHJlc291cmNlcy5nZXQoa2V5KTsKICAgIH0KCiAgICBwdWJsaWMgYm9vbGVhbiBnZXRSb2xsYmFja09ubHkoKSB7CiAgICAgICAgcmV0dXJuIHN0YXR1cyA9PSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgIH0KCiAgICBwdWJsaWMgT2JqZWN0IGdldFRyYW5zYWN0aW9uS2V5KCkgewogICAgICAgIHJldHVybiB4aWQ7CiAgICB9CgogICAgcHVibGljIGludCBnZXRUcmFuc2FjdGlvblN0YXR1cygpIHsKICAgICAgICByZXR1cm4gc3RhdHVzOwogICAgfQoKICAgIHB1YmxpYyB2b2lkIHB1dFJlc291cmNlKE9iamVjdCBrZXksIE9iamVjdCB2YWx1ZSkgewogICAgICAgIGlmIChrZXkgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oIllvdSBtdXN0IHN1cHBseSBhIG5vbi1udWxsIGtleSBmb3IgcHV0UmVzb3VyY2UiKTsKICAgICAgICB9CiAgICAgICAgcmVzb3VyY2VzLnB1dChrZXksIHZhbHVlKTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCByZWdpc3RlckludGVycG9zZWRTeW5jaHJvbml6YXRpb24oU3luY2hyb25pemF0aW9uIHN5bmNocm9uaXphdGlvbikgewogICAgICAgIGludGVycG9zZWRTeW5jTGlzdC5hZGQoc3luY2hyb25pemF0aW9uKTsKICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIHZvaWQgc2V0Um9sbGJhY2tPbmx5KCkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiB7CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s6CiAgICAgICAgICAgICAgICAvLyBub3RoaW5nIHRvIGRvCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIkNhbm5vdCBzZXQgcm9sbGJhY2sgb25seSwgc3RhdHVzIGlzICIgKyBnZXRTdGF0ZVN0cmluZyhzdGF0dXMpKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCB2b2lkIHJlZ2lzdGVyU3luY2hyb25pemF0aW9uKFN5bmNocm9uaXphdGlvbiBzeW5jaCkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiwgUm9sbGJhY2tFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgaWYgKHN5bmNoID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiU3luY2hyb25pemF0aW9uIGlzIG51bGwiKTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJUcmFuc2FjdGlvbiBpcyBtYXJrZWQgZm9yIHJvbGxiYWNrIik7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgIH0KICAgICAgICBzeW5jTGlzdC5hZGQoc3luY2gpOwogICAgfQoKICAgIHB1YmxpYyBzeW5jaHJvbml6ZWQgYm9vbGVhbiBlbmxpc3RSZXNvdXJjZShYQVJlc291cmNlIHhhUmVzKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBpZiAoeGFSZXMgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJYQVJlc291cmNlIGlzIG51bGwiKTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGFjdGl2ZVhhUmVzb3VyY2VzLmNvbnRhaW5zS2V5KHhhUmVzKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJ4YXJlc291cmNlOiAiICsgeGFSZXMgKyAiIGlzIGFscmVhZHkgZW5saXN0ZWQhIik7CiAgICAgICAgfQoKICAgICAgICB0cnkgewogICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSBzdXNwZW5kZWRYYVJlc291cmNlcy5yZW1vdmUoeGFSZXMpOwogICAgICAgICAgICBpZiAobWFuYWdlciAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICAvL3dlIGtub3cgYWJvdXQgdGhpcyBvbmUsIGl0IHdhcyBzdXNwZW5kZWQKICAgICAgICAgICAgICAgIHhhUmVzLnN0YXJ0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgWEFSZXNvdXJjZS5UTVJFU1VNRSk7CiAgICAgICAgICAgICAgICBhY3RpdmVYYVJlc291cmNlcy5wdXQoeGFSZXMsIG1hbmFnZXIpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy9pdCBpcyBub3Qgc3VzcGVuZGVkLgogICAgICAgICAgICBmb3IgKEl0ZXJhdG9yIGkgPSByZXNvdXJjZU1hbmFnZXJzLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7CiAgICAgICAgICAgICAgICBib29sZWFuIHNhbWVSTTsKICAgICAgICAgICAgICAgIC8vaWYgdGhlIHhhcmVzIGlzIGFscmVhZHkga25vd24sIHdlIG11c3QgYmUgcmVzdW1pbmcgYWZ0ZXIgYSBzdXNwZW5kLgogICAgICAgICAgICAgICAgaWYgKHhhUmVzID09IG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJ4YVJlcyAiICsgeGFSZXMgKyAiIGlzIGEgY29tbWl0dGVyIGJ1dCBpcyBub3QgYWN0aXZlIG9yIHN1c3BlbmRlZCIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy9PdGhlcndpc2UsIHNlZSBpZiB0aGlzIGlzIGEgbmV3IHhhcmVzIGZvciB0aGUgc2FtZSByZXNvdXJjZSBtYW5hZ2VyCiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHNhbWVSTSA9IHhhUmVzLmlzU2FtZVJNKG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkpOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKCJVbmV4cGVjdGVkIGVycm9yIGNoZWNraW5nIGZvciBzYW1lIFJNIiwgZSk7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoc2FtZVJNKSB7CiAgICAgICAgICAgICAgICAgICAgeGFSZXMuc3RhcnQobWFuYWdlci5nZXRCcmFuY2hJZCgpLCBYQVJlc291cmNlLlRNSk9JTik7CiAgICAgICAgICAgICAgICAgICAgYWN0aXZlWGFSZXNvdXJjZXMucHV0KHhhUmVzLCBtYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvL3dlIGtub3cgbm90aGluZyBhYm91dCB0aGlzIFhBUmVzb3VyY2Ugb3IgcmVzb3VyY2UgbWFuYWdlcgogICAgICAgICAgICBYaWQgYnJhbmNoSWQgPSB4aWRGYWN0b3J5LmNyZWF0ZUJyYW5jaCh4aWQsIHJlc291cmNlTWFuYWdlcnMuc2l6ZSgpICsgMSk7CiAgICAgICAgICAgIHhhUmVzLnN0YXJ0KGJyYW5jaElkLCBYQVJlc291cmNlLlRNTk9GTEFHUyk7CiAgICAgICAgICAgIGFjdGl2ZVhhUmVzb3VyY2VzLnB1dCh4YVJlcywgYWRkQnJhbmNoWGlkKHhhUmVzLCBicmFuY2hJZCkpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIGxvZy53YXJuKCJVbmFibGUgdG8gZW5saXN0IFhBUmVzb3VyY2UgIiArIHhhUmVzICsgIiwgZXJyb3JDb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICAvLyBtYXJrIHN0YXR1cyBhcyByb2xsYmFjayBvbmx5IGJlY2F1c2UgZW5saXN0IHJlc291cmNlIGZhaWxlZAogICAgICAgICAgICBzZXRSb2xsYmFja09ubHkoKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIGJvb2xlYW4gZGVsaXN0UmVzb3VyY2UoWEFSZXNvdXJjZSB4YVJlcywgaW50IGZsYWcpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgaWYgKCEoZmxhZyA9PSBYQVJlc291cmNlLlRNRkFJTCB8fCBmbGFnID09IFhBUmVzb3VyY2UuVE1TVUNDRVNTIHx8IGZsYWcgPT0gWEFSZXNvdXJjZS5UTVNVU1BFTkQpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oImludmFsaWQgZmxhZyBmb3IgZGVsaXN0UmVzb3VyY2U6ICIgKyBmbGFnKTsKICAgICAgICB9CiAgICAgICAgaWYgKHhhUmVzID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiWEFSZXNvdXJjZSBpcyBudWxsIik7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAoc3RhdHVzKSB7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgfQogICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGFjdGl2ZVhhUmVzb3VyY2VzLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgaWYgKG1hbmFnZXIgPT0gbnVsbCkgewogICAgICAgICAgICBpZiAoZmxhZyA9PSBYQVJlc291cmNlLlRNU1VTUEVORCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigidHJ5aW5nIHRvIHN1c3BlbmQgYW4gaW5hY3RpdmUgeGFyZXNvdXJjZTogIiArIHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvL25vdCBhY3RpdmUsIGFuZCB3ZSBhcmUgbm90IHRyeWluZyB0byBzdXNwZW5kLiAgV2UgbXVzdCBiZSBlbmRpbmcgdHguCiAgICAgICAgICAgIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIHN1c3BlbmRlZFhhUmVzb3VyY2VzLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgICAgIGlmIChtYW5hZ2VyID09IG51bGwpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlJlc291cmNlIG5vdCBrbm93biB0byB0cmFuc2FjdGlvbjogIiArIHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgeGFSZXMuZW5kKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgZmxhZyk7CiAgICAgICAgICAgIGlmIChmbGFnID09IFhBUmVzb3VyY2UuVE1TVVNQRU5EKSB7CiAgICAgICAgICAgICAgICBzdXNwZW5kZWRYYVJlc291cmNlcy5wdXQoeGFSZXMsIG1hbmFnZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgbG9nLndhcm4oIlVuYWJsZSB0byBkZWxpc3QgWEFSZXNvdXJjZSAiICsgeGFSZXMgKyAiLCBlcnJvciBjb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8vVHJhbnNhY3Rpb24gbWV0aG9kLCBkb2VzIDJwYwogICAgcHVibGljIHZvaWQgY29tbWl0KCkgdGhyb3dzIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbiwgUm9sbGJhY2tFeGNlcHRpb24sIFNlY3VyaXR5RXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIGJlZm9yZVByZXBhcmUoKTsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYm9vbGVhbiB0aW1lZG91dCA9IGZhbHNlOwogICAgICAgICAgICBpZiAoVHJhbnNhY3Rpb25UaW1lci5nZXRDdXJyZW50VGltZSgpID4gdGltZW91dCkgewogICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICB0aW1lZG91dCA9IHRydWU7CiAgICAgICAgICAgIH0gCgogICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLKSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlc0R1cmluZ0NvbW1pdChyZXNvdXJjZU1hbmFnZXJzLCBmYWxzZSk7CiAgICAgICAgICAgICAgICBpZiAodGltZWRvdXQpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlVuYWJsZSB0byBjb21taXQ6IFRyYW5zYWN0aW9uIHRpbWVvdXQiKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJVbmFibGUgdG8gY29tbWl0OiB0cmFuc2FjdGlvbiBtYXJrZWQgZm9yIHJvbGxiYWNrIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfQUNUSVZFKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBub3RoaW5nIHRvIGNvbW1pdAogICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBvbmUtcGhhc2UgY29tbWl0IGRlY2lzaW9uCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGFydCBwcmVwYXJlIHBhcnQgb2YgdHdvLXBoYXNlCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIHJlc291cmNlTWFuYWdlcnMgaXMgbm93IGltbXV0YWJsZQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBuby1waGFzZQogICAgICAgICAgICBpZiAocmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMCkgewogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIG9uZS1waGFzZQogICAgICAgICAgICBpZiAocmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMSkgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgcmVzb3VyY2VNYW5hZ2Vycy5nZXRGaXJzdCgpOwogICAgICAgICAgICAgICAgY29tbWl0UmVzb3VyY2UobWFuYWdlcik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0gCiAgICAgICAgICAgIAogICAgICAgICAgICBib29sZWFuIHdpbGxDb21taXQgPSBmYWxzZTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIC8vIHR3by1waGFzZQogICAgICAgICAgICAgICAgd2lsbENvbW1pdCA9IGludGVybmFsUHJlcGFyZSgpOwogICAgICAgICAgICB9IGNhdGNoIChTeXN0ZW1FeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXMocmVzb3VyY2VNYW5hZ2Vycyk7CiAgICAgICAgICAgICAgICB0aHJvdyBlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyBub3RpZnkgdGhlIFJNcwogICAgICAgICAgICBpZiAod2lsbENvbW1pdCkgewogICAgICAgICAgICAgICAgY29tbWl0UmVzb3VyY2VzKHJlc291cmNlTWFuYWdlcnMpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gc2V0IGV2ZXJSb2xsYmFjayB0byB0cnVlIGhlcmUgYmVjYXVzZSB0aGUgcm9sbGJhY2sgaGVyZSBpcyBjYXVzZWQgYnkgCiAgICAgICAgICAgICAgICAvLyBYQUV4Y2VwdGlvbiBkdXJpbmcgdGhlIGFib3ZlIGludGVybmFsUHJlcGFyZQogICAgICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXNEdXJpbmdDb21taXQocmVzb3VyY2VNYW5hZ2VycywgdHJ1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vVXNlZCBmcm9tIFhBVGVybWluYXRvciBmb3IgZmlyc3QgcGhhc2UgaW4gYSByZW1vdGVseSBjb250cm9sbGVkIHR4LgogICAgaW50IHByZXBhcmUoKSB0aHJvd3MgU3lzdGVtRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiB7CiAgICAgICAgYmVmb3JlUHJlcGFyZSgpOwogICAgICAgIGludCByZXN1bHQgPSBYQVJlc291cmNlLlhBX1JET05MWTsKICAgICAgICB0cnkgewogICAgICAgICAgICBMaW5rZWRMaXN0IHJtczsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfQUNUSVZFKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc291cmNlTWFuYWdlcnMuc2l6ZSgpID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyB0byBjb21taXQKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgcHJlcGFyZSBwYXJ0IG9mIHR3by1waGFzZQogICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyByZXNvdXJjZU1hbmFnZXJzIGlzIG5vdyBpbW11dGFibGUKICAgICAgICAgICAgICAgIHJtcyA9IHJlc291cmNlTWFuYWdlcnM7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGJvb2xlYW4gd2lsbENvbW1pdCA9IGludGVybmFsUHJlcGFyZSgpOwoKICAgICAgICAgICAgLy8gbm90aWZ5IHRoZSBSTXMKICAgICAgICAgICAgaWYgKHdpbGxDb21taXQpIHsKICAgICAgICAgICAgICAgIGlmICghcm1zLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFhBUmVzb3VyY2UuWEFfT0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhybXMpOwogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJVbmFibGUgdG8gY29tbWl0Iik7CiAgICAgICAgICAgIH0KICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09IFhBUmVzb3VyY2UuWEFfUkRPTkxZKSB7CiAgICAgICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICAvL3VzZWQgZnJvbSBYQVRlcm1pbmF0b3IgZm9yIGNvbW1pdCBwaGFzZSBvZiBub24tcmVhZG9ubHkgcmVtb3RlbHkgY29udHJvbGxlZCB0eC4KICAgIHZvaWQgcHJlcGFyZWRDb21taXQoKSB0aHJvd3MgSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24sIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbW1pdFJlc291cmNlcyhyZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vaGVscGVyIG1ldGhvZCB1c2VkIGJ5IFRyYW5zYWN0aW9uLmNvbW1pdCBhbmQgWEFUZXJtaW5hdG9yIHByZXBhcmUuCiAgICBwcml2YXRlIHZvaWQgYmVmb3JlUHJlcGFyZSgpIHsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBiZWZvcmVDb21wbGV0aW9uKCk7CiAgICAgICAgZW5kUmVzb3VyY2VzKCk7CiAgICB9CgoKICAgIC8vaGVscGVyIG1ldGhvZCB1c2VkIGJ5IFRyYW5zYWN0aW9uLmNvbW1pdCBhbmQgWEFUZXJtaW5hdG9yIHByZXBhcmUuCiAgICBwcml2YXRlIGJvb2xlYW4gaW50ZXJuYWxQcmVwYXJlKCkgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgZm9yIChJdGVyYXRvciBybXMgPSByZXNvdXJjZU1hbmFnZXJzLml0ZXJhdG9yKCk7IHJtcy5oYXNOZXh0KCk7KSB7CiAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgaWYgKHN0YXR1cyAhPSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORykgewogICAgICAgICAgICAgICAgICAgIC8vIHdlIHdlcmUgbWFya2VkIGZvciByb2xsYmFjawogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIHJtcy5uZXh0KCk7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBpbnQgdm90ZSA9IG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkucHJlcGFyZShtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgaWYgKHZvdGUgPT0gWEFSZXNvdXJjZS5YQV9SRE9OTFkpIHsKICAgICAgICAgICAgICAgICAgICAvLyB3ZSBkb24ndCBuZWVkIHRvIGNvbnNpZGVyIHRoaXMgUk0gYW55IG1vcmUKICAgICAgICAgICAgICAgICAgICBybXMucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIAogICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1BST1RPCiAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfSU5WQUwpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgcHJlcGFyZTsgdHJhbnNhY3Rpb24gd2FzIHJvbGxlZCBiYWNrIikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICAgICAgLyogUGVyIEpUQSBzcGVjLCAgSWYgdGhlIHJlc291cmNlIG1hbmFnZXIgd2FudHMgdG8gcm9sbCBiYWNrIHRoZSB0cmFuc2FjdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgaXQgc2hvdWxkIGRvIHNvIGJ5IHRocm93aW5nIGFuIGFwcHJvcHJpYXRlIFhBRXhjZXB0aW9uIGluIHRoZSBwcmVwYXJlIG1ldGhvZC4KICAgICAgICAgICAgICAgICAgICBBbHNvIHBlciBPVFMgc3BlYzoKICAgICAgICAgICAgICAgICAgICBUaGUgcmVzb3VyY2UgY2FuIHJldHVybiBWb3RlUm9sbGJhY2sgdW5kZXIgYW55IGNpcmN1bXN0YW5jZXMsIGluY2x1ZGluZyBub3QgaGF2aW5nIAogICAgICAgICAgICAgICAgICAgIGFueSBrbm93bGVkZ2UgYWJvdXQgdGhlIHRyYW5zYWN0aW9uICh3aGljaCBtaWdodCBoYXBwZW4gYWZ0ZXIgYSBjcmFzaCkuIElmIHRoaXMgCiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgaXMgcmV0dXJuZWQsIHRoZSB0cmFuc2FjdGlvbiBtdXN0IGJlIHJvbGxlZCBiYWNrLiBGdXJ0aGVybW9yZSwgdGhlIFRyYW5zYWN0aW9uIAogICAgICAgICAgICAgICAgICAgIFNlcnZpY2UgaXMgbm90IHJlcXVpcmVkIHRvIHBlcmZvcm0gYW55IGFkZGl0aW9uYWwgb3BlcmF0aW9ucyBvbiB0aGlzIHJlc291cmNlLiovCiAgICAgICAgICAgICAgICAgICAgLy9ybXMucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIGRlY2lzaW9uIHRpbWUuLi4KICAgICAgICBib29sZWFuIHdpbGxDb21taXQ7CiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHdpbGxDb21taXQgPSAoc3RhdHVzICE9IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLKTsKICAgICAgICAgICAgaWYgKHdpbGxDb21taXQpIHsKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSRUQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gbG9nIG91ciBkZWNpc2lvbgogICAgICAgIGlmICh3aWxsQ29tbWl0ICYmICFyZXNvdXJjZU1hbmFnZXJzLmlzRW1wdHkoKSkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgbG9nTWFyayA9IHR4bkxvZy5wcmVwYXJlKHhpZCwgcmVzb3VyY2VNYW5hZ2Vycyk7CiAgICAgICAgICAgIH0gY2F0Y2ggKExvZ0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHJvbGxiYWNrUmVzb3VyY2VzKHJlc291cmNlTWFuYWdlcnMpOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uIHNlKSB7CiAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJVbmFibGUgdG8gcm9sbGJhY2sgYWZ0ZXIgZmFpbHVyZSB0byBsb2cgcHJlcGFyZSIsIHNlLmdldENhdXNlKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgbG9nZ2luZyBwcmVwYXJlOyB0cmFuc2FjdGlvbiB3YXMgcm9sbGVkIGJhY2spIikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB3aWxsQ29tbWl0OwogICAgfQoKICAgIHB1YmxpYyB2b2lkIHJvbGxiYWNrKCkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBMaXN0IHJtczsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJTdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJtcyA9IHJlc291cmNlTWFuYWdlcnM7CiAgICAgICAgfQoKICAgICAgICBlbmRSZXNvdXJjZXMoKTsKICAgICAgICB0cnkgewogICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhybXMpOwogICAgICAgICAgICAvL29ubHkgd3JpdGUgcm9sbGJhY2sgcmVjb3JkIGlmIHdlIGhhdmUgYWxyZWFkeSB3cml0dGVuIHByZXBhcmUgcmVjb3JkLgogICAgICAgICAgICBpZiAobG9nTWFyayAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHR4bkxvZy5yb2xsYmFjayh4aWQsIGxvZ01hcmspOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhybXMpOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBzZSkgewogICAgICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuYWJsZSB0byByb2xsYmFjayBhZnRlciBmYWlsdXJlIHRvIGxvZyBkZWNpc2lvbiIsIHNlLmdldENhdXNlKCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBsb2dnaW5nIHJvbGxiYWNrIikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgICAgYWZ0ZXJDb21wbGV0aW9uKCk7CiAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19OT19UUkFOU0FDVElPTjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHZvaWQgYmVmb3JlQ29tcGxldGlvbigpIHsKICAgICAgICBiZWZvcmVDb21wbGV0aW9uKHN5bmNMaXN0KTsKICAgICAgICBiZWZvcmVDb21wbGV0aW9uKGludGVycG9zZWRTeW5jTGlzdCk7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGJlZm9yZUNvbXBsZXRpb24oTGlzdCBzeW5jcykgewogICAgICAgIGludCBpID0gMDsKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICBTeW5jaHJvbml6YXRpb24gc3luY2g7CiAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgaWYgKGkgPT0gc3luY3Muc2l6ZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBzeW5jaCA9IChTeW5jaHJvbml6YXRpb24pIHN5bmNzLmdldChpKyspOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBzeW5jaC5iZWZvcmVDb21wbGV0aW9uKCk7CiAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBsb2cud2FybigiVW5leHBlY3RlZCBleGNlcHRpb24gZnJvbSBiZWZvcmVDb21wbGV0aW9uOyB0cmFuc2FjdGlvbiB3aWxsIHJvbGwgYmFjayIsIGUpOwogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGFmdGVyQ29tcGxldGlvbigpIHsKICAgICAgICAvLyB0aGlzIGRvZXMgbm90IHN5bmNocm9uaXplIGJlY2F1c2Ugbm90aGluZyBjYW4gbW9kaWZ5IG91ciBzdGF0ZSBhdCB0aGlzIHRpbWUKICAgICAgICBhZnRlckNvbXBsZXRpb24oaW50ZXJwb3NlZFN5bmNMaXN0KTsKICAgICAgICBhZnRlckNvbXBsZXRpb24oc3luY0xpc3QpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCBhZnRlckNvbXBsZXRpb24oTGlzdCBzeW5jcykgewogICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHN5bmNzLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICBTeW5jaHJvbml6YXRpb24gc3luY2ggPSAoU3luY2hyb25pemF0aW9uKSBpLm5leHQoKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHN5bmNoLmFmdGVyQ29tcGxldGlvbihzdGF0dXMpOwogICAgICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgbG9nLndhcm4oIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGZyb20gYWZ0ZXJDb21wbGV0aW9uOyBjb250aW51aW5nIiwgZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGVuZFJlc291cmNlcygpIHsKICAgICAgICBlbmRSZXNvdXJjZXMoYWN0aXZlWGFSZXNvdXJjZXMpOwogICAgICAgIGVuZFJlc291cmNlcyhzdXNwZW5kZWRYYVJlc291cmNlcyk7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGVuZFJlc291cmNlcyhJZGVudGl0eUhhc2hNYXAgcmVzb3VyY2VNYXApIHsKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICBYQVJlc291cmNlIHhhUmVzOwogICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyOwogICAgICAgICAgICBpbnQgZmxhZ3M7CiAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgU2V0IGVudHJ5U2V0ID0gcmVzb3VyY2VNYXAuZW50cnlTZXQoKTsKICAgICAgICAgICAgICAgIGlmIChlbnRyeVNldC5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBNYXAuRW50cnkgZW50cnkgPSAoTWFwLkVudHJ5KSBlbnRyeVNldC5pdGVyYXRvcigpLm5leHQoKTsKICAgICAgICAgICAgICAgIHhhUmVzID0gKFhBUmVzb3VyY2UpIGVudHJ5LmdldEtleSgpOwogICAgICAgICAgICAgICAgbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgZW50cnkuZ2V0VmFsdWUoKTsKICAgICAgICAgICAgICAgIGZsYWdzID0gKHN0YXR1cyA9PSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSykgPyBYQVJlc291cmNlLlRNRkFJTCA6IFhBUmVzb3VyY2UuVE1TVUNDRVNTOwogICAgICAgICAgICAgICAgcmVzb3VyY2VNYXAucmVtb3ZlKHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgeGFSZXMuZW5kKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgZmxhZ3MpOwogICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBsb2cud2FybigiRXJyb3IgZW5kaW5nIGFzc29jaWF0aW9uIGZvciBYQVJlc291cmNlICIgKyB4YVJlcyArICI7IHRyYW5zYWN0aW9uIHdpbGwgcm9sbCBiYWNrLiBYQSBlcnJvciBjb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIHJvbGxiYWNrUmVzb3VyY2VzKExpc3Qgcm1zKSB0aHJvd3MgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBTeXN0ZW1FeGNlcHRpb24gY2F1c2UgPSBudWxsOwogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExJTkdfQkFDSzsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBpID0gcm1zLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkucm9sbGJhY2sobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIHJvbGxpbmcgYmFjayAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgd2l0aCByb2xsYmFjayIsIGUpOwogICAgICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0J3Mgbm90IHNldCB0aGUgY2F1c2UgaGVyZQogICAgICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSByb2xsZWQgYmFjayAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgd2l0aCByb2xsYmFjayIsIGUpOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfUkJST0xMQkFDSyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1GQUlMKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCBzZXQgdGhlIGNhdXNlIGhlcmUgYmVjYXVzZSB3ZSBleHBlY3QgdGhlIHRyYW5zYWN0aW9uIHRvIGJlIHJvbGxlZCBiYWNrIGV2ZW50dWFsbHkKICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogZm9yIFJNRkFJTCwgaXQgbWVhbnMgcmVzb3VyY2UgdW5hdmFpbGFibGUgdGVtcG9yYXJpbHkuICAKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG8gd2UgbmVlZCBrZWVwIHNlbmRpbmcgcmVxdWVzdCB0byByZXNvdXJjZSB0byBtYWtlIHN1cmUgdGhlIHJvbGwgYmFjayBjb21wbGV0ZXM/CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gbmV3IFN5c3RlbUV4Y2VwdGlvbihlLmVycm9yQ29kZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgcm9sbGluZyBiYWNrIikuaW5pdENhdXNlKGUpOyAgICAgICAgICAgIAogICAgICAgIH0gICAgICAgICAgICAKCiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUk9MTEVEQkFDSzsKICAgICAgICB9CiAgICAgICAgaWYgKGNhdXNlICE9IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgY2F1c2U7CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCByb2xsYmFja1Jlc291cmNlc0R1cmluZ0NvbW1pdChMaXN0IHJtcywgYm9vbGVhbiBldmVyUmIpIHRocm93cyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbiwgUm9sbGJhY2tFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgWEFFeGNlcHRpb24gY2F1c2UgPSBudWxsOwogICAgICAgIGJvb2xlYW4gZXZlclJvbGxlZGJhY2sgPSBldmVyUmI7CiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUk9MTElOR19CQUNLOwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgICBmb3IgKEl0ZXJhdG9yIGkgPSBybXMuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7KSB7CiAgICAgICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSBpLm5leHQoKTsKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5yb2xsYmFjayhtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIGV2ZXJSb2xsZWRiYWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCBzZXQgdGhlIGNhdXNlIGhlcmUgYXMgdGhlIHJlc3VsdGluZyBiZWhhdmlvciBpcyBzYW1lIGFzIHJlcXVlc3RlZCBiZWhhdmlvcgogICAgICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgcm9sbGVkIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlclJvbGxlZGJhY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIGFuZCByb2xsZWQgYmFjayAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgd2l0aCByb2xsYmFjayIsIGUpOwogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZXJSb2xsZWRiYWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJDT00pIHsKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiBoZXVyaXN0aWNhbGx5IGNvbW1pdHRlZCAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgd2l0aCByb2xsYmFjayIsIGUpOwogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9SQlJPTExCQUNLIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9STUVSUgogICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRkFJTCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBYQUV4Y2VwdGlvbi5YQV9SQlJPTExCQUNLIGR1cmluZyBjb21taXQvcm9sbGJhY2ssIHRodXMgUm9sbGJhY2tFeGNlcHRpb24gaXMgZXhwZWN0ZWQKICAgICAgICAgICAgICAgICAgICAgICAgLy8gWEFFeGNlcHRpb24uWEFFUl9STUVSUiBtZWFucyB0cmFuc2FjdGlvbiBicmFuY2ggZXJyb3IgYW5kIHRyYW5zYWN0aW9uIGhhcyBiZWVuIHJvbGxlZCBiYWNrCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCBzZXQgdGhlIGNhdXNlIGhlcmUgYmVjYXVzZSB3ZSBleHBlY3QgdGhlIHRyYW5zYWN0aW9uIHRvIGJlIHJvbGxlZCBiYWNrIGV2ZW50dWFsbHkKICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogZm9yIFJNRkFJTCwgaXQgbWVhbnMgcmVzb3VyY2UgdW5hdmFpbGFibGUgdGVtcG9yYXJpbHkuICAKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG8gd2UgbmVlZCBrZWVwIHNlbmRpbmcgcmVxdWVzdCB0byByZXNvdXJjZSB0byBtYWtlIHN1cmUgdGhlIHJvbGwgYmFjayBjb21wbGV0ZXM/CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZSA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIlN5c3RlbSBlcnJvciBkdXJpbmcgY29tbWl0L3JvbGxpbmcgYmFjayIpLmluaXRDYXVzZShlKTsgICAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUk9MTEVEQkFDSzsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYgKGNhdXNlID09IG51bGwpIHsKICAgICAgICAgICAgdGhyb3cgKFJvbGxiYWNrRXhjZXB0aW9uKSBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlVuYWJsZSB0byBjb21taXQ6IHRyYW5zYWN0aW9uIG1hcmtlZCBmb3Igcm9sbGJhY2siKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUkNPTSAmJiBldmVyUm9sbGVkYmFjaykgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkhldXJpc3RpY01peGVkIGVycm9yIGR1cmluZyBjb21taXQvcm9sbGluZyBiYWNrIikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkhldXJpc3RpY01peGVkIGVycm9yIGR1cmluZyBjb21taXQvcm9sbGluZyBiYWNrIikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIlN5c3RlbSBFcnJvciBkdXJpbmcgY29tbWl0L3JvbGxpbmcgYmFjayIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gCiAgICAgICAgfQogICAgfQogICAgCiAgICBwcml2YXRlIHZvaWQgY29tbWl0UmVzb3VyY2UoVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlcikgdGhyb3dzIFJvbGxiYWNrRXhjZXB0aW9uLCBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbiwgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbnsKICAgICAgICBYQUV4Y2VwdGlvbiBjYXVzZSA9IG51bGw7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgdHJ5IHsKCiAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmNvbW1pdChtYW5hZ2VyLmdldEJyYW5jaElkKCksIHRydWUpOwogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRURUQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUk9MTEVEQkFDSzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQikgewogICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIC8vdGhyb3cgKEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24oIkVycm9yIGR1cmluZyBvbmUtcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7CiAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyBvbmUtcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSQ09NKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gbGV0J3Mgbm90IHRocm93IGFuIGV4Y2VwdGlvbiBhcyB0aGUgdHJhbnNhY3Rpb24gaGFzIGJlZW4gY29tbWl0dGVkCiAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIik7CiAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfUkJST0xMQkFDSyAKICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9STUVSUiAKICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gUGVyIFhBIHNwZWMsIFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgZnJvbSBjb21taXQgbWVhbnMgQW4gZXJyb3Igb2NjdXJyZWQgaW4gCiAgICAgICAgICAgICAgICAgICAgLy8gY29tbWl0dGluZyB0aGUgd29yayBwZXJmb3JtZWQgb24gYmVoYWxmIG9mIHRoZSB0cmFuc2FjdGlvbiBicmFuY2ggCiAgICAgICAgICAgICAgICAgICAgLy8gYW5kIHRoZSBicmFuY2jVcyB3b3JrIGhhcyBiZWVuIHJvbGxlZCBiYWNrLiAKICAgICAgICAgICAgICAgICAgICAvLyBYQUV4Y2VwdGlvbi5YQUVSX05PVEE6ICBzc3VtZSB0aGUgREIgdG9vayBhIHVuaWxhdGVyYWwgcm9sbGJhY2sgZGVjaXNpb24gYW5kIGZvcmdvdCB0aGUgdHJhbnNhY3Rpb24KICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gcm9sbGVkIGJhY2siKTsKICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgLy8gdGhyb3cgKFJvbGxiYWNrRXhjZXB0aW9uKSBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIkVycm9yIGR1cmluZyBvbmUtcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOyAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgLy90aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgb25lLXBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBKSB7CiAgICAgICAgICAgICAgICAvLyBOT1RBIGluIHJlc3BvbnNlIHRvIGZvcmdldCwgbWVhbnMgdGhlIHJlc291cmNlIGFscmVhZHkgZm9yZ290IHRoZSB0cmFuc2FjdGlvbgogICAgICAgICAgICAgICAgLy8gaWdub3JlCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgb25lIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAoY2F1c2UgIT0gbnVsbCkgewogICAgICAgICAgICBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQikgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfUkJST0xMQkFDSyAKICAgICAgICAgICAgICAgICAgICB8fCBjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9STUVSUiAKICAgICAgICAgICAgICAgICAgICB8fCBjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IAogICAgICAgIH0KICAgIH0KICAgIAogICAgcHJpdmF0ZSB2b2lkIGNvbW1pdFJlc291cmNlcyhMaXN0IHJtcykgdGhyb3dzIEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uLCBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBYQUV4Y2VwdGlvbiBjYXVzZSA9IG51bGw7CiAgICAgICAgYm9vbGVhbiBldmVyY29tbWl0ID0gZmFsc2U7CiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBpID0gcm1zLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuY29tbWl0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIGV2ZXJjb21taXQgPSB0cnVlOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVW5leHBlY3RlZCBleGNlcHRpb24gY29tbWl0dGluZyAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgdG8gY29tbWl0IG90aGVyIFJNcyIsIGUpOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgcm9sbGVkIGJhY2siKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSBjb21taXR0ZWQgYW5kIHJvbGxlZCBiYWNrIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlcmNvbW1pdCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSQ09NKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCB0aHJvdyBhbiBleGNlcHRpb24gYXMgdGhlIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGNvbW1pdHRlZAogICAgICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSBjb21taXR0ZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlcmNvbW1pdCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfTk9UQSkgewogICAgICAgICAgICAgICAgLy8gTk9UQSBpbiByZXNwb25zZSB0byBmb3JnZXQsIG1lYW5zIHRoZSByZXNvdXJjZSBhbHJlYWR5IGZvcmdvdCB0aGUgdHJhbnNhY3Rpb24KICAgICAgICAgICAgICAgIC8vIGlnbm9yZQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy9pZiBhbGwgcmVzb3VyY2VzIHdlcmUgcmVhZCBvbmx5LCB3ZSBkaWRuJ3Qgd3JpdGUgYSBwcmVwYXJlIHJlY29yZC4KICAgICAgICBpZiAoIXJtcy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHR4bkxvZy5jb21taXQoeGlkLCBsb2dNYXJrKTsKICAgICAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVW5leHBlY3RlZCBleGNlcHRpb24gbG9nZ2luZyBjb21taXQgY29tcGxldGlvbiBmb3IgeGlkICIgKyB4aWQsIGUpOwogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiVW5leHBlY3RlZCBlcnJvciBsb2dnaW5nIGNvbW1pdCBjb21wbGV0aW9uIGZvciB4aWQgIiArIHhpZCkuaW5pdENhdXNlKGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICB9CiAgICAgICAgaWYgKGNhdXNlICE9IG51bGwpIHsKICAgICAgICAgICAgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIgJiYgIWV2ZXJjb21taXQpIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbikgbmV3IEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQiAmJiBldmVyY29tbWl0KSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IAogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmcgZ2V0U3RhdGVTdHJpbmcoaW50IHN0YXR1cykgewogICAgICAgIHN3aXRjaCAoc3RhdHVzKSB7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19BQ1RJVkU6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19BQ1RJVkUiOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfUFJFUEFSSU5HIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUkVEOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfUFJFUEFSRUQiOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfTUFSS0VEX1JPTExCQUNLIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1JPTExJTkdfQkFDSzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1JPTExJTkdfQkFDSyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19DT01NSVRUSU5HOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfQ09NTUlUVElORyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19DT01NSVRURUQ6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19DT01NSVRURUQiOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfUk9MTEVEQkFDSzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1JPTExFREJBQ0siOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT046CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19OT19UUkFOU0FDVElPTiI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19VTktOT1dOOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfVU5LTk9XTiI7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoKTsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIGJvb2xlYW4gZXF1YWxzKE9iamVjdCBvYmopIHsKICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgVHJhbnNhY3Rpb25JbXBsKSB7CiAgICAgICAgICAgIFRyYW5zYWN0aW9uSW1wbCBvdGhlciA9IChUcmFuc2FjdGlvbkltcGwpIG9iajsKICAgICAgICAgICAgcmV0dXJuIHhpZC5lcXVhbHMob3RoZXIueGlkKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8vd2hlbiB1c2VkIGZyb20gcmVjb3ZlcnksIGRvIG5vdCBhZGQgbWFuYWdlciB0byBhY3RpdmUgb3Igc3VzcGVuZGVkIHJlc291cmNlIG1hcHMuCiAgICAvLyBUaGUgeGFyZXNvdXJjZXMgaGF2ZSBhbHJlYWR5IGJlZW4gZW5kZWQgd2l0aCBUTVNVQ0NFU1MuCiAgICBwdWJsaWMgVHJhbnNhY3Rpb25CcmFuY2ggYWRkQnJhbmNoWGlkKFhBUmVzb3VyY2UgeGFSZXMsIFhpZCBicmFuY2hJZCkgewogICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSBuZXcgVHJhbnNhY3Rpb25CcmFuY2goeGFSZXMsIGJyYW5jaElkKTsKICAgICAgICByZXNvdXJjZU1hbmFnZXJzLmFkZChtYW5hZ2VyKTsKICAgICAgICByZXR1cm4gbWFuYWdlcjsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBjbGFzcyBUcmFuc2FjdGlvbkJyYW5jaCBpbXBsZW1lbnRzIFRyYW5zYWN0aW9uQnJhbmNoSW5mbyB7CiAgICAgICAgcHJpdmF0ZSBmaW5hbCBYQVJlc291cmNlIGNvbW1pdHRlcjsKICAgICAgICBwcml2YXRlIGZpbmFsIFhpZCBicmFuY2hJZDsKCiAgICAgICAgcHVibGljIFRyYW5zYWN0aW9uQnJhbmNoKFhBUmVzb3VyY2UgeGFSZXMsIFhpZCBicmFuY2hJZCkgewogICAgICAgICAgICBjb21taXR0ZXIgPSB4YVJlczsKICAgICAgICAgICAgdGhpcy5icmFuY2hJZCA9IGJyYW5jaElkOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFhBUmVzb3VyY2UgZ2V0Q29tbWl0dGVyKCkgewogICAgICAgICAgICByZXR1cm4gY29tbWl0dGVyOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFhpZCBnZXRCcmFuY2hJZCgpIHsKICAgICAgICAgICAgcmV0dXJuIGJyYW5jaElkOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFN0cmluZyBnZXRSZXNvdXJjZU5hbWUoKSB7CiAgICAgICAgICAgIGlmIChjb21taXR0ZXIgaW5zdGFuY2VvZiBOYW1lZFhBUmVzb3VyY2UpIHsKICAgICAgICAgICAgICAgIHJldHVybiAoKE5hbWVkWEFSZXNvdXJjZSkgY29tbWl0dGVyKS5nZXROYW1lKCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBpZiBpdCBpc24ndCBhIG5hbWVkIHJlc291cmNlIHNob3VsZCB3ZSByZWFsbHkgc3RvcCBhbGwgcHJvY2Vzc2luZyBoZXJlIQogICAgICAgICAgICAgICAgLy8gTWF5YmUgdGhpcyB3b3VsZCBiZSBiZXR0ZXIgdG8gaGFuZGxlIGVsc2Ugd2hlcmUgYW5kIGRvIHdlIHJlYWxseSB3YW50IHRvIHByZXZlbnQgYWxsIHByb2Nlc3Npbmcgb2YgdHJhbnNhY3Rpb25zPwogICAgICAgICAgICAgICAgbG9nLmVycm9yKCJQbGVhc2UgY29ycmVjdCB0aGUgaW50ZWdyYXRpb24gYW5kIHN1cHBseSBhIE5hbWVkWEFSZXNvdXJjZSIsIG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIkNhbm5vdCBsb2cgdHJhbnNhY3Rpb25zIGFzICIgKyBjb21taXR0ZXIgKyAiIGlzIG5vdCBhIE5hbWVkWEFSZXNvdXJjZS4iKSk7CiAgICAgICAgICAgICAgICByZXR1cm4gY29tbWl0dGVyLnRvU3RyaW5nKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHB1YmxpYyBYaWQgZ2V0QnJhbmNoWGlkKCkgewogICAgICAgICAgICByZXR1cm4gYnJhbmNoSWQ7CiAgICAgICAgfQogICAgfQoKCn0K