Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8KLy8gIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmUgb3IgbW9yZQovLyAgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZSBkaXN0cmlidXRlZCB3aXRoCi8vICB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCi8vICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZSB0byBZb3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMAovLyAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGgKLy8gIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0Ci8vCi8vICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCi8vCi8vICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCi8vICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCi8vICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCi8vICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KLy8KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnBhY2thZ2UgY29tLmFkb2JlLmxpbmd1aXN0aWNzLnNwZWxsaW5nIHsKICAgIGltcG9ydCBjb20uYWRvYmUubGluZ3Vpc3RpY3Muc3BlbGxpbmcuU3BlbGxVSTsKICAgIGltcG9ydCBjb20uYWRvYmUubGluZ3Vpc3RpY3Muc3BlbGxpbmcuZnJhbWV3b3JrLlNwZWxsaW5nU2VydmljZTsKICAgIGltcG9ydCBjb20uYWRvYmUubGluZ3Vpc3RpY3Muc3BlbGxpbmcuZnJhbWV3b3JrLnVpLklIaWdobGlnaHRlcjsKCiAgICBpbXBvcnQgZmxhc2guZXZlbnRzLkV2ZW50OwogICAgaW1wb3J0IGZsYXNoLmV2ZW50cy5JRXZlbnREaXNwYXRjaGVyOwoKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5lZGl0LkVkaXRNYW5hZ2VyOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLkZsb3dFbGVtZW50OwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLlBhcmFncmFwaEVsZW1lbnQ7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZWxlbWVudHMuU3BhbkVsZW1lbnQ7CgogICAgaW1wb3J0IG1vY2tvbGF0ZS5uaWNlOwogICAgaW1wb3J0IG1vY2tvbGF0ZS5wcmVwYXJlOwogICAgaW1wb3J0IG1vY2tvbGF0ZS5yZWNlaXZlZDsKICAgIGltcG9ydCBtb2Nrb2xhdGUuc3R1YjsKCiAgICBpbXBvcnQgb3JnLmZsZXh1bml0LmFzc2VydFRoYXQ7CiAgICBpbXBvcnQgb3JnLmZsZXh1bml0LmFzc2VydHMuYXNzZXJ0VHJ1ZTsKICAgIGltcG9ydCBvcmcuZmxleHVuaXQuYXN5bmMuQXN5bmM7CiAgICBpbXBvcnQgb3JnLmZsdWludC51aUltcGVyc29uYXRpb24uVUlJbXBlcnNvbmF0b3I7CgogICAgaW1wb3J0IHNwYXJrLmNvbXBvbmVudHMuUmljaEVkaXRhYmxlVGV4dDsKCiAgICBwdWJsaWMgY2xhc3MgRkxFWF8zNDc1Nl9UZXN0IHsKICAgICAgICBwcml2YXRlIHN0YXRpYyB2YXIgX3RleHRGaWVsZDpSaWNoRWRpdGFibGVUZXh0OwogICAgICAgIHByaXZhdGUgc3RhdGljIHZhciBfc3V0OlNwZWxsVUk7CiAgICAgICAgcHJpdmF0ZSBzdGF0aWMgY29uc3QgVEVYVF9XSVRIX1NQRUxMSU5HX0VSUk9SOlN0cmluZyA9ICJoZWxsb28iOwogICAgICAgIHByaXZhdGUgc3RhdGljIGNvbnN0IERJQ1Q6U3RyaW5nID0gImVuX0dCIjsKCiAgICAgICAgW0JlZm9yZShhc3luYywgdGltZW91dD01MDAwKV0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0VXAoKTp2b2lkCiAgICAgICAgewogICAgICAgICAgICBfdGV4dEZpZWxkID0gbmV3IFJpY2hFZGl0YWJsZVRleHQoKTsKICAgICAgICAgICAgVUlJbXBlcnNvbmF0b3IuYWRkQ2hpbGQoX3RleHRGaWVsZCk7CiAgICAgICAgICAgIF90ZXh0RmllbGQudGV4dCA9IFRFWFRfV0lUSF9TUEVMTElOR19FUlJPUjsKCiAgICAgICAgICAgIHZhciBtb2Nrb2xhdGVEaXNwYXRjaGVyOklFdmVudERpc3BhdGNoZXIgPSBwcmVwYXJlKElIaWdobGlnaHRlciwgU3BlbGxpbmdTZXJ2aWNlKTsKICAgICAgICAgICAgbW9ja29sYXRlRGlzcGF0Y2hlci5hZGRFdmVudExpc3RlbmVyKEV2ZW50LkNPTVBMRVRFLCBBc3luYy5hc3luY0hhbmRsZXIodGhpcywgb25TZXRVcENvbXBsZXRlLCA1MDAwLCBudWxsLCBudWxsKSk7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHN0YXRpYyBmdW5jdGlvbiBvblNldFVwQ29tcGxldGUoZXZlbnQ6RXZlbnQsIHBhc3NUaHJvdWdoRGF0YTpPYmplY3QpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIFNwZWxsVUlGb3JUZXN0LnNwYXJrSGlnaGxpZ2h0ZXIgPSBuaWNlKElIaWdobGlnaHRlcik7CiAgICAgICAgICAgIFNwZWxsVUlGb3JUZXN0LnNwZWxsaW5nU2VydmljZSA9IG5pY2UoU3BlbGxpbmdTZXJ2aWNlLCAic3BlbGxpbmdTZXJ2aWNlIiwgW0RJQ1RdKTsKCiAgICAgICAgICAgIF9zdXQgPSBuZXcgU3BlbGxVSUZvclRlc3QoX3RleHRGaWVsZCwgRElDVCk7CiAgICAgICAgfQoKICAgICAgICBbQWZ0ZXJdCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHRlYXJEb3duKCk6dm9pZAogICAgICAgIHsKICAgICAgICAgICAgVUlJbXBlcnNvbmF0b3IucmVtb3ZlQWxsQ2hpbGRyZW4oKTsKICAgICAgICAgICAgX3RleHRGaWVsZCA9IG51bGw7CiAgICAgICAgICAgIF9zdXQgPSBudWxsOwogICAgICAgIH0KCiAgICAgICAgW1Rlc3QoYXN5bmMsIHRpbWVvdXQ9MjUwMCldCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIG1ha2Vfc3VyZV9pdF9kb2VzbnRfcnVuX2Ffc3BlbGxpbmdfam9iX29uX2RhbWFnZWRfdGV4dF9mbG93KCk6dm9pZAogICAgICAgIHsKICAgICAgICAgICAgLy93aGVuCiAgICAgICAgICAgIHN0dWIoU3BlbGxVSUZvclRlc3Quc3BlbGxpbmdTZXJ2aWNlKS5tZXRob2QoImluaXQiKS5kaXNwYXRjaGVzKG5ldyBFdmVudChFdmVudC5DT01QTEVURSkpOwogICAgICAgICAgICBTcGVsbFVJLmVuYWJsZVNwZWxsaW5nKF90ZXh0RmllbGQsICJlbl9HQiIpOwogICAgICAgICAgICBTcGVsbFVJRm9yVGVzdC5ldmVudERpc3BhdGNoZXIuYWRkRXZlbnRMaXN0ZW5lcihFdmVudC5DT01QTEVURSwgQXN5bmMuYXN5bmNIYW5kbGVyKHRoaXMsIG9uRGljdGlvbmFyeUxvYWRDb21wbGV0ZSwgMTUwMCwgbnVsbCwgbnVsbCkpOwogICAgICAgIH0KCiAgICAgICAgcHJpdmF0ZSBmdW5jdGlvbiBvbkRpY3Rpb25hcnlMb2FkQ29tcGxldGUoZXZlbnQ6RXZlbnQsIHBhc3NUaHJvdWdoRGF0YTpPYmplY3QpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIC8vZ2l2ZW4KICAgICAgICAgICAgZGFtYWdlVGV4dEZsb3coKTsKCiAgICAgICAgICAgIC8vd2hlbgogICAgICAgICAgICBfc3V0LmRvU3BlbGxpbmdKb2IoKTsKCiAgICAgICAgICAgIC8vdGhlbgogICAgICAgICAgICAvL2RvU3BlbGxpbmdKb2IoKSBpcyBhbHNvIGNhbGxlZCBvbmNlIGFmdGVyIHRoZSBkaWN0aW9uYXJ5IGZpbmlzaGVzIGxvYWRpbmcsIGhlbmNlICdhdE1vc3QoMSknIGJlbG93CiAgICAgICAgICAgIGFzc2VydFRoYXQoU3BlbGxVSUZvclRlc3Quc3BhcmtIaWdobGlnaHRlciwgcmVjZWl2ZWQoKS5tZXRob2QoImNsZWFyU3F1aWdnbGVzIikuYXRNb3N0KDEpKTsKICAgICAgICAgICAgYXNzZXJ0VGhhdChTcGVsbFVJRm9yVGVzdC5zcGVsbGluZ1NlcnZpY2UsIHJlY2VpdmVkKCkubWV0aG9kKCJjaGVja1dvcmQiKS5uZXZlcigpKTsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgZnVuY3Rpb24gZGFtYWdlVGV4dEZsb3coKTp2b2lkCiAgICAgICAgewogICAgICAgICAgICB2YXIgZWRpdE1hbmFnZXI6RWRpdE1hbmFnZXIgPSBfdGV4dEZpZWxkLnRleHRGbG93LmludGVyYWN0aW9uTWFuYWdlciBhcyBFZGl0TWFuYWdlcjsKICAgICAgICAgICAgdmFyIGZpcnN0TGluZTpGbG93RWxlbWVudCA9IGVkaXRNYW5hZ2VyLnRleHRGbG93LmZpbmRMZWFmKDApOwogICAgICAgICAgICB2YXIgcGFyYWdyYXBoOlBhcmFncmFwaEVsZW1lbnQgPSBmaXJzdExpbmUuZ2V0UGFyYWdyYXBoKCk7CiAgICAgICAgICAgIHZhciBzcGFuOlNwYW5FbGVtZW50ID0gbmV3IFNwYW5FbGVtZW50KCk7CiAgICAgICAgICAgIHNwYW4udGV4dCA9ICIgIJUgICI7CiAgICAgICAgICAgIHBhcmFncmFwaC5hZGRDaGlsZEF0KDAsIHNwYW4pOwoKICAgICAgICAgICAgYXNzZXJ0VHJ1ZShfdGV4dEZpZWxkLnRleHRGbG93LmZsb3dDb21wb3Nlci5pc0RhbWFnZWQoX3RleHRGaWVsZC50ZXh0Rmxvdy50ZXh0TGVuZ3RoKSk7CiAgICAgICAgfQogICAgfQp9CgppbXBvcnQgY29tLmFkb2JlLmxpbmd1aXN0aWNzLnNwZWxsaW5nLlNwZWxsVUk7CmltcG9ydCBjb20uYWRvYmUubGluZ3Vpc3RpY3Muc3BlbGxpbmcuZnJhbWV3b3JrLlNwZWxsaW5nU2VydmljZTsKaW1wb3J0IGNvbS5hZG9iZS5saW5ndWlzdGljcy5zcGVsbGluZy5mcmFtZXdvcmsudWkuSGFsb0hpZ2hsaWdodGVyOwppbXBvcnQgY29tLmFkb2JlLmxpbmd1aXN0aWNzLnNwZWxsaW5nLmZyYW1ld29yay51aS5JSGlnaGxpZ2h0ZXI7CgppbXBvcnQgZmxhc2guZXZlbnRzLkV2ZW50OwppbXBvcnQgZmxhc2guZXZlbnRzLkV2ZW50RGlzcGF0Y2hlcjsKaW1wb3J0IGZsYXNoLmV2ZW50cy5JRXZlbnREaXNwYXRjaGVyOwppbXBvcnQgZmxhc2guZXZlbnRzLlRpbWVyRXZlbnQ7CmltcG9ydCBmbGFzaC51dGlscy5UaW1lcjsKCmNsYXNzIFNwZWxsVUlGb3JUZXN0IGV4dGVuZHMgU3BlbGxVSQp7CiAgICBwdWJsaWMgc3RhdGljIHZhciBzcGFya0hpZ2hsaWdodGVyOklIaWdobGlnaHRlcjsKICAgIHB1YmxpYyBzdGF0aWMgdmFyIHNwZWxsaW5nU2VydmljZTpTcGVsbGluZ1NlcnZpY2U7CiAgICBwdWJsaWMgc3RhdGljIHZhciBldmVudERpc3BhdGNoZXI6SUV2ZW50RGlzcGF0Y2hlciA9IG5ldyBFdmVudERpc3BhdGNoZXIoKTsKICAgIHByaXZhdGUgc3RhdGljIHZhciBfdGltZXI6VGltZXIgPSBuZXcgVGltZXIoMTAwLCAxKTsKCiAgICBwdWJsaWMgZnVuY3Rpb24gU3BlbGxVSUZvclRlc3QodGV4dE1vZGVsOiosIGxhbmc6U3RyaW5nKQogICAgewogICAgICAgIF90aW1lci5hZGRFdmVudExpc3RlbmVyKFRpbWVyRXZlbnQuVElNRVJfQ09NUExFVEUsIG9uVGltZXIpOwogICAgICAgIHN1cGVyKHRleHRNb2RlbCwgbGFuZyk7CiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBvblRpbWVyKGV2ZW50OlRpbWVyRXZlbnQpOnZvaWQKICAgIHsKICAgICAgICBldmVudERpc3BhdGNoZXIuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoRXZlbnQuQ09NUExFVEUpKTsKICAgIH0KCiAgICBvdmVycmlkZSBwcm90ZWN0ZWQgZnVuY3Rpb24gY3JlYXRlSGlnaGxpZ2h0ZXIoaXNIYWxvQ29tb3BvbmVudDpCb29sZWFuLCBwYXJlbnQ6Kik6SUhpZ2hsaWdodGVyCiAgICB7CiAgICAgICAgLy93ZSdyZSBub3QgZGlzcGF0Y2hpbmcgdGhlIGNvbXBsZXRlIGV2ZW50IGp1c3QgeWV0IGJlY2F1c2UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlCiAgICAgICAgLy9zb21lIGV4dHJhIHByb2Nlc3NpbmcgaXMgZG9uZSBhZnRlciB0aGUgZGljdGlvbmFyeSBpcyBsb2FkZWQuIFNlZSBTcGVsbFVJLmFkZENvbnRleHRNZW51KCkKICAgICAgICBfdGltZXIuc3RvcCgpOwogICAgICAgIF90aW1lci5yZXNldCgpOwogICAgICAgIF90aW1lci5zdGFydCgpOwoKICAgICAgICByZXR1cm4gaXNIYWxvQ29tb3BvbmVudCA/IG5ldyBIYWxvSGlnaGxpZ2h0ZXIocGFyZW50KSA6IHNwYXJrSGlnaGxpZ2h0ZXI7CiAgICB9CgogICAgb3ZlcnJpZGUgcHJvdGVjdGVkIGZ1bmN0aW9uIGNyZWF0ZVNwZWxsaW5nU2VydmljZShkaWN0aW9uYXJ5TmFtZTpTdHJpbmcpOlNwZWxsaW5nU2VydmljZQogICAgewogICAgICAgIHJldHVybiBzcGVsbGluZ1NlcnZpY2U7CiAgICB9Cgp9Cg==