LyoqCiAqICBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lIG9yIG1vcmUKICogIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiAgdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLgogKiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGUgdG8gWW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAKICogICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqICB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogKgogKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCgpwYWNrYWdlIG9yZy5hcGFjaGUuZ2Vyb25pbW8udHJhbnNhY3Rpb24ubWFuYWdlcjsKCmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSWRlbnRpdHlIYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLkl0ZXJhdG9yOwppbXBvcnQgamF2YS51dGlsLkxpbmtlZExpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuU2V0OwoKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLkhldXJpc3RpY01peGVkRXhjZXB0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24uSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi5Sb2xsYmFja0V4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlN0YXR1czsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlN5bmNocm9uaXphdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlN5c3RlbUV4Y2VwdGlvbjsKaW1wb3J0IGphdmF4LnRyYW5zYWN0aW9uLlRyYW5zYWN0aW9uOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24ueGEuWEFFeGNlcHRpb247CmltcG9ydCBqYXZheC50cmFuc2FjdGlvbi54YS5YQVJlc291cmNlOwppbXBvcnQgamF2YXgudHJhbnNhY3Rpb24ueGEuWGlkOwppbXBvcnQgb3JnLnNsZjRqLkxvZ2dlcjsKaW1wb3J0IG9yZy5zbGY0ai5Mb2dnZXJGYWN0b3J5OwoKCi8qKgogKiBCYXNpYyBsb2NhbCB0cmFuc2FjdGlvbiB3aXRoIHN1cHBvcnQgZm9yIG11bHRpcGxlIHJlc291cmNlcy4KICoKICogQHZlcnNpb24gJFJldiQgJERhdGUkCiAqLwpwdWJsaWMgY2xhc3MgVHJhbnNhY3Rpb25JbXBsIGltcGxlbWVudHMgVHJhbnNhY3Rpb24gewogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgTG9nZ2VyIGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKCJUcmFuc2FjdGlvbiIpOwoKICAgIHByaXZhdGUgZmluYWwgWGlkRmFjdG9yeSB4aWRGYWN0b3J5OwogICAgcHJpdmF0ZSBmaW5hbCBYaWQgeGlkOwogICAgcHJpdmF0ZSBmaW5hbCBUcmFuc2FjdGlvbkxvZyB0eG5Mb2c7CiAgICBwcml2YXRlIGZpbmFsIFJldHJ5U2NoZWR1bGVyIHJldHJ5U2NoZWR1bGVyOwogICAgcHJpdmF0ZSBmaW5hbCBsb25nIHRpbWVvdXQ7CiAgICBwcml2YXRlIGZpbmFsIExpc3Q8U3luY2hyb25pemF0aW9uPiBzeW5jTGlzdCA9IG5ldyBBcnJheUxpc3Q8U3luY2hyb25pemF0aW9uPig1KTsKICAgIHByaXZhdGUgZmluYWwgTGlzdDxTeW5jaHJvbml6YXRpb24+IGludGVycG9zZWRTeW5jTGlzdCA9IG5ldyBBcnJheUxpc3Q8U3luY2hyb25pemF0aW9uPigzKTsKICAgIHByaXZhdGUgZmluYWwgTGlua2VkTGlzdDxUcmFuc2FjdGlvbkJyYW5jaD4gcmVzb3VyY2VNYW5hZ2VycyA9IG5ldyBMaW5rZWRMaXN0PFRyYW5zYWN0aW9uQnJhbmNoPigpOwogICAgcHJpdmF0ZSBmaW5hbCBJZGVudGl0eUhhc2hNYXA8WEFSZXNvdXJjZSwgVHJhbnNhY3Rpb25CcmFuY2g+IGFjdGl2ZVhhUmVzb3VyY2VzID0gbmV3IElkZW50aXR5SGFzaE1hcDxYQVJlc291cmNlLCBUcmFuc2FjdGlvbkJyYW5jaD4oMyk7CiAgICBwcml2YXRlIGZpbmFsIElkZW50aXR5SGFzaE1hcDxYQVJlc291cmNlLCBUcmFuc2FjdGlvbkJyYW5jaD4gc3VzcGVuZGVkWGFSZXNvdXJjZXMgPSBuZXcgSWRlbnRpdHlIYXNoTWFwPFhBUmVzb3VyY2UsIFRyYW5zYWN0aW9uQnJhbmNoPigzKTsKICAgIHByaXZhdGUgaW50IHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICBwcml2YXRlIE9iamVjdCBsb2dNYXJrOwoKICAgIHByaXZhdGUgZmluYWwgTWFwPE9iamVjdCwgT2JqZWN0PiByZXNvdXJjZXMgPSBuZXcgSGFzaE1hcDxPYmplY3QsIE9iamVjdD4oKTsKCiAgICBUcmFuc2FjdGlvbkltcGwoWGlkRmFjdG9yeSB4aWRGYWN0b3J5LCBUcmFuc2FjdGlvbkxvZyB0eG5Mb2csIFJldHJ5U2NoZWR1bGVyIHJldHJ5U2NoZWR1bGVyLCBsb25nIHRyYW5zYWN0aW9uVGltZW91dE1pbGxpc2Vjb25kcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdGhpcyh4aWRGYWN0b3J5LmNyZWF0ZVhpZCgpLCB4aWRGYWN0b3J5LCB0eG5Mb2csIHJldHJ5U2NoZWR1bGVyLCB0cmFuc2FjdGlvblRpbWVvdXRNaWxsaXNlY29uZHMpOwogICAgfQoKICAgIFRyYW5zYWN0aW9uSW1wbChYaWQgeGlkLCBYaWRGYWN0b3J5IHhpZEZhY3RvcnksIFRyYW5zYWN0aW9uTG9nIHR4bkxvZywgUmV0cnlTY2hlZHVsZXIgcmV0cnlTY2hlZHVsZXIsIGxvbmcgdHJhbnNhY3Rpb25UaW1lb3V0TWlsbGlzZWNvbmRzKSB0aHJvd3MgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICB0aGlzLnhpZEZhY3RvcnkgPSB4aWRGYWN0b3J5OwogICAgICAgIHRoaXMudHhuTG9nID0gdHhuTG9nOwogICAgICAgIHRoaXMucmV0cnlTY2hlZHVsZXIgPSByZXRyeVNjaGVkdWxlcjsKICAgICAgICB0aGlzLnhpZCA9IHhpZDsKICAgICAgICB0aGlzLnRpbWVvdXQgPSB0cmFuc2FjdGlvblRpbWVvdXRNaWxsaXNlY29uZHMgKyBUcmFuc2FjdGlvblRpbWVyLmdldEN1cnJlbnRUaW1lKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgdHhuTG9nLmJlZ2luKHhpZCk7CiAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgIFN5c3RlbUV4Y2VwdGlvbiBleCA9IG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGxvZ2dpbmcgYmVnaW47IHRyYW5zYWN0aW9uIG1hcmtlZCBmb3Igcm9sbCBiYWNrKSIpOwogICAgICAgICAgICBleC5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0FDVElWRTsKICAgIH0KCiAgICAvL3JlY29uc3RydWN0IGEgdHggZm9yIGFuIGV4dGVybmFsIHR4IGZvdW5kIGluIHJlY292ZXJ5CiAgICBwdWJsaWMgVHJhbnNhY3Rpb25JbXBsKFhpZCB4aWQsIFRyYW5zYWN0aW9uTG9nIHR4TG9nLCBSZXRyeVNjaGVkdWxlciByZXRyeVNjaGVkdWxlcikgewogICAgICAgIHRoaXMueGlkRmFjdG9yeSA9IG51bGw7CiAgICAgICAgdGhpcy50eG5Mb2cgPSB0eExvZzsKICAgICAgICB0aGlzLnhpZCA9IHhpZDsKICAgICAgICB0aGlzLnJldHJ5U2NoZWR1bGVyID0gcmV0cnlTY2hlZHVsZXI7CiAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19QUkVQQVJFRDsKICAgICAgICAvL1RPRE8gaXMgdGhpcyBhIGdvb2QgaWRlYT8KICAgICAgICB0aGlzLnRpbWVvdXQgPSBMb25nLk1BWF9WQUxVRTsKICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIGludCBnZXRTdGF0dXMoKSB7CiAgICAgICAgcmV0dXJuIHN0YXR1czsKICAgIH0KCiAgICBwdWJsaWMgT2JqZWN0IGdldFJlc291cmNlKE9iamVjdCBrZXkpIHsKICAgICAgICByZXR1cm4gcmVzb3VyY2VzLmdldChrZXkpOwogICAgfQoKICAgIHB1YmxpYyBib29sZWFuIGdldFJvbGxiYWNrT25seSgpIHsKICAgICAgICByZXR1cm4gc3RhdHVzID09IFN0YXR1cy5TVEFUVVNfTUFSS0VEX1JPTExCQUNLOwogICAgfQoKICAgIHB1YmxpYyBPYmplY3QgZ2V0VHJhbnNhY3Rpb25LZXkoKSB7CiAgICAgICAgcmV0dXJuIHhpZDsKICAgIH0KCiAgICBwdWJsaWMgaW50IGdldFRyYW5zYWN0aW9uU3RhdHVzKCkgewogICAgICAgIHJldHVybiBzdGF0dXM7CiAgICB9CgogICAgcHVibGljIHZvaWQgcHV0UmVzb3VyY2UoT2JqZWN0IGtleSwgT2JqZWN0IHZhbHVlKSB7CiAgICAgICAgaWYgKGtleSA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBOdWxsUG9pbnRlckV4Y2VwdGlvbigiWW91IG11c3Qgc3VwcGx5IGEgbm9uLW51bGwga2V5IGZvciBwdXRSZXNvdXJjZSIpOwogICAgICAgIH0KICAgICAgICByZXNvdXJjZXMucHV0KGtleSwgdmFsdWUpOwogICAgfQoKICAgIHB1YmxpYyB2b2lkIHJlZ2lzdGVySW50ZXJwb3NlZFN5bmNocm9uaXphdGlvbihTeW5jaHJvbml6YXRpb24gc3luY2hyb25pemF0aW9uKSB7CiAgICAgICAgaW50ZXJwb3NlZFN5bmNMaXN0LmFkZChzeW5jaHJvbml6YXRpb24pOwogICAgfQoKICAgIHB1YmxpYyBzeW5jaHJvbml6ZWQgdm9pZCBzZXRSb2xsYmFja09ubHkoKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uIHsKICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOgogICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzoKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1JPTExJTkdfQkFDSzoKICAgICAgICAgICAgICAgIC8vIG5vdGhpbmcgdG8gZG8KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiQ2Fubm90IHNldCByb2xsYmFjayBvbmx5LCBzdGF0dXMgaXMgIiArIGdldFN0YXRlU3RyaW5nKHN0YXR1cykpOwogICAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3luY2hyb25pemVkIHZvaWQgcmVnaXN0ZXJTeW5jaHJvbml6YXRpb24oU3luY2hyb25pemF0aW9uIHN5bmNoKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBpZiAoc3luY2ggPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJTeW5jaHJvbml6YXRpb24gaXMgbnVsbCIpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlRyYW5zYWN0aW9uIGlzIG1hcmtlZCBmb3Igcm9sbGJhY2siKTsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgfQogICAgICAgIHN5bmNMaXN0LmFkZChzeW5jaCk7CiAgICB9CgogICAgcHVibGljIHN5bmNocm9uaXplZCBib29sZWFuIGVubGlzdFJlc291cmNlKFhBUmVzb3VyY2UgeGFSZXMpIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24sIFJvbGxiYWNrRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIGlmICh4YVJlcyA9PSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIlhBUmVzb3VyY2UgaXMgbnVsbCIpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoYWN0aXZlWGFSZXNvdXJjZXMuY29udGFpbnNLZXkoeGFSZXMpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oInhhcmVzb3VyY2U6ICIgKyB4YVJlcyArICIgaXMgYWxyZWFkeSBlbmxpc3RlZCEiKTsKICAgICAgICB9CgogICAgICAgIHRyeSB7CiAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIHN1c3BlbmRlZFhhUmVzb3VyY2VzLnJlbW92ZSh4YVJlcyk7CiAgICAgICAgICAgIGlmIChtYW5hZ2VyICE9IG51bGwpIHsKICAgICAgICAgICAgICAgIC8vd2Uga25vdyBhYm91dCB0aGlzIG9uZSwgaXQgd2FzIHN1c3BlbmRlZAogICAgICAgICAgICAgICAgeGFSZXMuc3RhcnQobWFuYWdlci5nZXRCcmFuY2hJZCgpLCBYQVJlc291cmNlLlRNUkVTVU1FKTsKICAgICAgICAgICAgICAgIGFjdGl2ZVhhUmVzb3VyY2VzLnB1dCh4YVJlcywgbWFuYWdlcik7CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvL2l0IGlzIG5vdCBzdXNwZW5kZWQuCiAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJlc291cmNlTWFuYWdlcnMuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7KSB7CiAgICAgICAgICAgICAgICBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSBpLm5leHQoKTsKICAgICAgICAgICAgICAgIGJvb2xlYW4gc2FtZVJNOwogICAgICAgICAgICAgICAgLy9pZiB0aGUgeGFyZXMgaXMgYWxyZWFkeSBrbm93biwgd2UgbXVzdCBiZSByZXN1bWluZyBhZnRlciBhIHN1c3BlbmQuCiAgICAgICAgICAgICAgICBpZiAoeGFSZXMgPT0gbWFuYWdlci5nZXRDb21taXR0ZXIoKSkgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oInhhUmVzICIgKyB4YVJlcyArICIgaXMgYSBjb21taXR0ZXIgYnV0IGlzIG5vdCBhY3RpdmUgb3Igc3VzcGVuZGVkIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvL090aGVyd2lzZSwgc2VlIGlmIHRoaXMgaXMgYSBuZXcgeGFyZXMgZm9yIHRoZSBzYW1lIHJlc291cmNlIG1hbmFnZXIKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgc2FtZVJNID0geGFSZXMuaXNTYW1lUk0obWFuYWdlci5nZXRDb21taXR0ZXIoKSk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4oIlVuZXhwZWN0ZWQgZXJyb3IgY2hlY2tpbmcgZm9yIHNhbWUgUk0iLCBlKTsKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzYW1lUk0pIHsKICAgICAgICAgICAgICAgICAgICB4YVJlcy5zdGFydChtYW5hZ2VyLmdldEJyYW5jaElkKCksIFhBUmVzb3VyY2UuVE1KT0lOKTsKICAgICAgICAgICAgICAgICAgICBhY3RpdmVYYVJlc291cmNlcy5wdXQoeGFSZXMsIG1hbmFnZXIpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vd2Uga25vdyBub3RoaW5nIGFib3V0IHRoaXMgWEFSZXNvdXJjZSBvciByZXNvdXJjZSBtYW5hZ2VyCiAgICAgICAgICAgIFhpZCBicmFuY2hJZCA9IHhpZEZhY3RvcnkuY3JlYXRlQnJhbmNoKHhpZCwgcmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgKyAxKTsKICAgICAgICAgICAgeGFSZXMuc3RhcnQoYnJhbmNoSWQsIFhBUmVzb3VyY2UuVE1OT0ZMQUdTKTsKICAgICAgICAgICAgYWN0aXZlWGFSZXNvdXJjZXMucHV0KHhhUmVzLCBhZGRCcmFuY2hYaWQoeGFSZXMsIGJyYW5jaElkKSk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgbG9nLndhcm4oIlVuYWJsZSB0byBlbmxpc3QgWEFSZXNvdXJjZSAiICsgeGFSZXMgKyAiLCBlcnJvckNvZGU6ICIgKyBlLmVycm9yQ29kZSwgZSk7CiAgICAgICAgICAgIC8vIG1hcmsgc3RhdHVzIGFzIHJvbGxiYWNrIG9ubHkgYmVjYXVzZSBlbmxpc3QgcmVzb3VyY2UgZmFpbGVkCiAgICAgICAgICAgIHNldFJvbGxiYWNrT25seSgpOwogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzeW5jaHJvbml6ZWQgYm9vbGVhbiBkZWxpc3RSZXNvdXJjZShYQVJlc291cmNlIHhhUmVzLCBpbnQgZmxhZykgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBpZiAoIShmbGFnID09IFhBUmVzb3VyY2UuVE1GQUlMIHx8IGZsYWcgPT0gWEFSZXNvdXJjZS5UTVNVQ0NFU1MgfHwgZmxhZyA9PSBYQVJlc291cmNlLlRNU1VTUEVORCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiaW52YWxpZCBmbGFnIGZvciBkZWxpc3RSZXNvdXJjZTogIiArIGZsYWcpOwogICAgICAgIH0KICAgICAgICBpZiAoeGFSZXMgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJYQVJlc291cmNlIGlzIG51bGwiKTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzoKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiU3RhdHVzIGlzICIgKyBnZXRTdGF0ZVN0cmluZyhzdGF0dXMpKTsKICAgICAgICB9CiAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgYWN0aXZlWGFSZXNvdXJjZXMucmVtb3ZlKHhhUmVzKTsKICAgICAgICBpZiAobWFuYWdlciA9PSBudWxsKSB7CiAgICAgICAgICAgIGlmIChmbGFnID09IFhBUmVzb3VyY2UuVE1TVVNQRU5EKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJ0cnlpbmcgdG8gc3VzcGVuZCBhbiBpbmFjdGl2ZSB4YXJlc291cmNlOiAiICsgeGFSZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vbm90IGFjdGl2ZSwgYW5kIHdlIGFyZSBub3QgdHJ5aW5nIHRvIHN1c3BlbmQuICBXZSBtdXN0IGJlIGVuZGluZyB0eC4KICAgICAgICAgICAgbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgc3VzcGVuZGVkWGFSZXNvdXJjZXMucmVtb3ZlKHhhUmVzKTsKICAgICAgICAgICAgaWYgKG1hbmFnZXIgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiUmVzb3VyY2Ugbm90IGtub3duIHRvIHRyYW5zYWN0aW9uOiAiICsgeGFSZXMpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0cnkgewogICAgICAgICAgICB4YVJlcy5lbmQobWFuYWdlci5nZXRCcmFuY2hJZCgpLCBmbGFnKTsKICAgICAgICAgICAgaWYgKGZsYWcgPT0gWEFSZXNvdXJjZS5UTVNVU1BFTkQpIHsKICAgICAgICAgICAgICAgIHN1c3BlbmRlZFhhUmVzb3VyY2VzLnB1dCh4YVJlcywgbWFuYWdlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICBsb2cud2FybigiVW5hYmxlIHRvIGRlbGlzdCBYQVJlc291cmNlICIgKyB4YVJlcyArICIsIGVycm9yIGNvZGU6ICIgKyBlLmVycm9yQ29kZSwgZSk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICB9CgogICAgLy9UcmFuc2FjdGlvbiBtZXRob2QsIGRvZXMgMnBjCiAgICBwdWJsaWMgdm9pZCBjb21taXQoKSB0aHJvd3MgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24sIEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiwgU2VjdXJpdHlFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgYmVmb3JlUHJlcGFyZSgpOwoKICAgICAgICB0cnkgewogICAgICAgICAgICBib29sZWFuIHRpbWVkb3V0ID0gZmFsc2U7CiAgICAgICAgICAgIGlmIChUcmFuc2FjdGlvblRpbWVyLmdldEN1cnJlbnRUaW1lKCkgPiB0aW1lb3V0KSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgICAgICAgICAgICAgIHRpbWVkb3V0ID0gdHJ1ZTsKICAgICAgICAgICAgfSAKCiAgICAgICAgICAgIGlmIChzdGF0dXMgPT0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0spIHsKICAgICAgICAgICAgICAgIHJvbGxiYWNrUmVzb3VyY2VzRHVyaW5nQ29tbWl0KHJlc291cmNlTWFuYWdlcnMsIGZhbHNlKTsKICAgICAgICAgICAgICAgIGlmICh0aW1lZG91dCkgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSb2xsYmFja0V4Y2VwdGlvbigiVW5hYmxlIHRvIGNvbW1pdDogVHJhbnNhY3Rpb24gdGltZW91dCIpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlVuYWJsZSB0byBjb21taXQ6IHRyYW5zYWN0aW9uIG1hcmtlZCBmb3Igcm9sbGJhY2siKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT0gU3RhdHVzLlNUQVRVU19BQ1RJVkUpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXNvdXJjZU1hbmFnZXJzLnNpemUoKSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vdGhpbmcgdG8gY29tbWl0CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVEVEOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5yZXNvdXJjZU1hbmFnZXJzLnNpemUoKSA9PSAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9uZS1waGFzZSBjb21taXQgZGVjaXNpb24KICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19DT01NSVRUSU5HOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0IHByZXBhcmUgcGFydCBvZiB0d28tcGhhc2UKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19QUkVQQVJJTkc7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gcmVzb3VyY2VNYW5hZ2VycyBpcyBub3cgaW1tdXRhYmxlCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIG5vLXBoYXNlCiAgICAgICAgICAgIGlmIChyZXNvdXJjZU1hbmFnZXJzLnNpemUoKSA9PSAwKSB7CiAgICAgICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gb25lLXBoYXNlCiAgICAgICAgICAgIGlmIChyZXNvdXJjZU1hbmFnZXJzLnNpemUoKSA9PSAxKSB7CiAgICAgICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gKFRyYW5zYWN0aW9uQnJhbmNoKSByZXNvdXJjZU1hbmFnZXJzLmdldEZpcnN0KCk7CiAgICAgICAgICAgICAgICBjb21taXRSZXNvdXJjZShtYW5hZ2VyKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfSAKICAgICAgICAgICAgCiAgICAgICAgICAgIGJvb2xlYW4gd2lsbENvbW1pdCA9IGZhbHNlOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgLy8gdHdvLXBoYXNlCiAgICAgICAgICAgICAgICB3aWxsQ29tbWl0ID0gaW50ZXJuYWxQcmVwYXJlKCk7CiAgICAgICAgICAgIH0gY2F0Y2ggKFN5c3RlbUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlcyhyZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICAgICAgICAgIHRocm93IGU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIG5vdGlmeSB0aGUgUk1zCiAgICAgICAgICAgIGlmICh3aWxsQ29tbWl0KSB7CiAgICAgICAgICAgICAgICBjb21taXRSZXNvdXJjZXMocmVzb3VyY2VNYW5hZ2Vycyk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBzZXQgZXZlclJvbGxiYWNrIHRvIHRydWUgaGVyZSBiZWNhdXNlIHRoZSByb2xsYmFjayBoZXJlIGlzIGNhdXNlZCBieSAKICAgICAgICAgICAgICAgIC8vIFhBRXhjZXB0aW9uIGR1cmluZyB0aGUgYWJvdmUgaW50ZXJuYWxQcmVwYXJlCiAgICAgICAgICAgICAgICByb2xsYmFja1Jlc291cmNlc0R1cmluZ0NvbW1pdChyZXNvdXJjZU1hbmFnZXJzLCB0cnVlKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGFmdGVyQ29tcGxldGlvbigpOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy9Vc2VkIGZyb20gWEFUZXJtaW5hdG9yIGZvciBmaXJzdCBwaGFzZSBpbiBhIHJlbW90ZWx5IGNvbnRyb2xsZWQgdHguCiAgICBpbnQgcHJlcGFyZSgpIHRocm93cyBTeXN0ZW1FeGNlcHRpb24sIFJvbGxiYWNrRXhjZXB0aW9uIHsKICAgICAgICBiZWZvcmVQcmVwYXJlKCk7CiAgICAgICAgaW50IHJlc3VsdCA9IFhBUmVzb3VyY2UuWEFfUkRPTkxZOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIExpbmtlZExpc3Qgcm1zOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT0gU3RhdHVzLlNUQVRVU19BQ1RJVkUpIHsKICAgICAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VNYW5hZ2Vycy5zaXplKCkgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBub3RoaW5nIHRvIGNvbW1pdAogICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGFydCBwcmVwYXJlIHBhcnQgb2YgdHdvLXBoYXNlCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIHJlc291cmNlTWFuYWdlcnMgaXMgbm93IGltbXV0YWJsZQogICAgICAgICAgICAgICAgcm1zID0gcmVzb3VyY2VNYW5hZ2VyczsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYm9vbGVhbiB3aWxsQ29tbWl0ID0gaW50ZXJuYWxQcmVwYXJlKCk7CgogICAgICAgICAgICAvLyBub3RpZnkgdGhlIFJNcwogICAgICAgICAgICBpZiAod2lsbENvbW1pdCkgewogICAgICAgICAgICAgICAgaWYgKCFybXMuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gWEFSZXNvdXJjZS5YQV9PSzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHJvbGxiYWNrUmVzb3VyY2VzKHJtcyk7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUm9sbGJhY2tFeGNlcHRpb24oIlVuYWJsZSB0byBjb21taXQiKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGlmIChyZXN1bHQgPT0gWEFSZXNvdXJjZS5YQV9SRE9OTFkpIHsKICAgICAgICAgICAgICAgIGFmdGVyQ29tcGxldGlvbigpOwogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19OT19UUkFOU0FDVElPTjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIC8vdXNlZCBmcm9tIFhBVGVybWluYXRvciBmb3IgY29tbWl0IHBoYXNlIG9mIG5vbi1yZWFkb25seSByZW1vdGVseSBjb250cm9sbGVkIHR4LgogICAgdm9pZCBwcmVwYXJlZENvbW1pdCgpIHRocm93cyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbiwgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24sIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgY29tbWl0UmVzb3VyY2VzKHJlc291cmNlTWFuYWdlcnMpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGFmdGVyQ29tcGxldGlvbigpOwogICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfTk9fVFJBTlNBQ1RJT047CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy9oZWxwZXIgbWV0aG9kIHVzZWQgYnkgVHJhbnNhY3Rpb24uY29tbWl0IGFuZCBYQVRlcm1pbmF0b3IgcHJlcGFyZS4KICAgIHByaXZhdGUgdm9pZCBiZWZvcmVQcmVwYXJlKCkgewogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGJlZm9yZUNvbXBsZXRpb24oKTsKICAgICAgICBlbmRSZXNvdXJjZXMoKTsKICAgIH0KCgogICAgLy9oZWxwZXIgbWV0aG9kIHVzZWQgYnkgVHJhbnNhY3Rpb24uY29tbWl0IGFuZCBYQVRlcm1pbmF0b3IgcHJlcGFyZS4KICAgIHByaXZhdGUgYm9vbGVhbiBpbnRlcm5hbFByZXBhcmUoKSB0aHJvd3MgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBmb3IgKEl0ZXJhdG9yIHJtcyA9IHJlc291cmNlTWFuYWdlcnMuaXRlcmF0b3IoKTsgcm1zLmhhc05leHQoKTspIHsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RhdHVzICE9IFN0YXR1cy5TVEFUVVNfUFJFUEFSSU5HKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gd2Ugd2VyZSBtYXJrZWQgZm9yIHJvbGxiYWNrCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgcm1zLm5leHQoKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIGludCB2b3RlID0gbWFuYWdlci5nZXRDb21taXR0ZXIoKS5wcmVwYXJlKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICBpZiAodm90ZSA9PSBYQVJlc291cmNlLlhBX1JET05MWSkgewogICAgICAgICAgICAgICAgICAgIC8vIHdlIGRvbid0IG5lZWQgdG8gY29uc2lkZXIgdGhpcyBSTSBhbnkgbW9yZQogICAgICAgICAgICAgICAgICAgIHJtcy5yZW1vdmUoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1FUlIgCiAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUFJPVE8KICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9JTlZBTCkgewogICAgICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyBwcmVwYXJlOyB0cmFuc2FjdGlvbiB3YXMgcm9sbGVkIGJhY2siKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgICAgICAgICAgICAgICAgICAvKiBQZXIgSlRBIHNwZWMsICBJZiB0aGUgcmVzb3VyY2UgbWFuYWdlciB3YW50cyB0byByb2xsIGJhY2sgdGhlIHRyYW5zYWN0aW9uLCAKICAgICAgICAgICAgICAgICAgICBpdCBzaG91bGQgZG8gc28gYnkgdGhyb3dpbmcgYW4gYXBwcm9wcmlhdGUgWEFFeGNlcHRpb24gaW4gdGhlIHByZXBhcmUgbWV0aG9kLgogICAgICAgICAgICAgICAgICAgIEFsc28gcGVyIE9UUyBzcGVjOgogICAgICAgICAgICAgICAgICAgIFRoZSByZXNvdXJjZSBjYW4gcmV0dXJuIFZvdGVSb2xsYmFjayB1bmRlciBhbnkgY2lyY3Vtc3RhbmNlcywgaW5jbHVkaW5nIG5vdCBoYXZpbmcgCiAgICAgICAgICAgICAgICAgICAgYW55IGtub3dsZWRnZSBhYm91dCB0aGUgdHJhbnNhY3Rpb24gKHdoaWNoIG1pZ2h0IGhhcHBlbiBhZnRlciBhIGNyYXNoKS4gSWYgdGhpcyAKICAgICAgICAgICAgICAgICAgICByZXNwb25zZSBpcyByZXR1cm5lZCwgdGhlIHRyYW5zYWN0aW9uIG11c3QgYmUgcm9sbGVkIGJhY2suIEZ1cnRoZXJtb3JlLCB0aGUgVHJhbnNhY3Rpb24gCiAgICAgICAgICAgICAgICAgICAgU2VydmljZSBpcyBub3QgcmVxdWlyZWQgdG8gcGVyZm9ybSBhbnkgYWRkaXRpb25hbCBvcGVyYXRpb25zIG9uIHRoaXMgcmVzb3VyY2UuKi8KICAgICAgICAgICAgICAgICAgICAvL3Jtcy5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gZGVjaXNpb24gdGltZS4uLgogICAgICAgIGJvb2xlYW4gd2lsbENvbW1pdDsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgd2lsbENvbW1pdCA9IChzdGF0dXMgIT0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0spOwogICAgICAgICAgICBpZiAod2lsbENvbW1pdCkgewogICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19QUkVQQVJFRDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyBsb2cgb3VyIGRlY2lzaW9uCiAgICAgICAgaWYgKHdpbGxDb21taXQgJiYgIXJlc291cmNlTWFuYWdlcnMuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBsb2dNYXJrID0gdHhuTG9nLnByZXBhcmUoeGlkLCByZXNvdXJjZU1hbmFnZXJzKTsKICAgICAgICAgICAgfSBjYXRjaCAoTG9nRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgcm9sbGJhY2tSZXNvdXJjZXMocmVzb3VyY2VNYW5hZ2Vycyk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gc2UpIHsKICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuYWJsZSB0byByb2xsYmFjayBhZnRlciBmYWlsdXJlIHRvIGxvZyBwcmVwYXJlIiwgc2UuZ2V0Q2F1c2UoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBsb2dnaW5nIHByZXBhcmU7IHRyYW5zYWN0aW9uIHdhcyByb2xsZWQgYmFjaykiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHdpbGxDb21taXQ7CiAgICB9CgogICAgcHVibGljIHZvaWQgcm9sbGJhY2soKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uLCBTeXN0ZW1FeGNlcHRpb24gewogICAgICAgIExpc3Qgcm1zOwogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX0FDVElWRToKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s6CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlN0YXR1cyBpcyAiICsgZ2V0U3RhdGVTdHJpbmcoc3RhdHVzKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcm1zID0gcmVzb3VyY2VNYW5hZ2VyczsKICAgICAgICB9CgogICAgICAgIGVuZFJlc291cmNlcygpOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIHJvbGxiYWNrUmVzb3VyY2VzKHJtcyk7CiAgICAgICAgICAgIC8vb25seSB3cml0ZSByb2xsYmFjayByZWNvcmQgaWYgd2UgaGF2ZSBhbHJlYWR5IHdyaXR0ZW4gcHJlcGFyZSByZWNvcmQuCiAgICAgICAgICAgIGlmIChsb2dNYXJrICE9IG51bGwpIHsKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgdHhuTG9nLnJvbGxiYWNrKHhpZCwgbG9nTWFyayk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChMb2dFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJvbGxiYWNrUmVzb3VyY2VzKHJtcyk7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uIHNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVW5hYmxlIHRvIHJvbGxiYWNrIGFmdGVyIGZhaWx1cmUgdG8gbG9nIGRlY2lzaW9uIiwgc2UuZ2V0Q2F1c2UoKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGxvZ2dpbmcgcm9sbGJhY2siKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBhZnRlckNvbXBsZXRpb24oKTsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgdm9pZCBiZWZvcmVDb21wbGV0aW9uKCkgewogICAgICAgIGJlZm9yZUNvbXBsZXRpb24oc3luY0xpc3QpOwogICAgICAgIGJlZm9yZUNvbXBsZXRpb24oaW50ZXJwb3NlZFN5bmNMaXN0KTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgYmVmb3JlQ29tcGxldGlvbihMaXN0IHN5bmNzKSB7CiAgICAgICAgaW50IGkgPSAwOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIFN5bmNocm9uaXphdGlvbiBzeW5jaDsKICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICBpZiAoaSA9PSBzeW5jcy5zaXplKCkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHN5bmNoID0gKFN5bmNocm9uaXphdGlvbikgc3luY3MuZ2V0KGkrKyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHN5bmNoLmJlZm9yZUNvbXBsZXRpb24oKTsKICAgICAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgICAgIGxvZy53YXJuKCJVbmV4cGVjdGVkIGV4Y2VwdGlvbiBmcm9tIGJlZm9yZUNvbXBsZXRpb247IHRyYW5zYWN0aW9uIHdpbGwgcm9sbCBiYWNrIiwgZSk7CiAgICAgICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHZvaWQgYWZ0ZXJDb21wbGV0aW9uKCkgewogICAgICAgIC8vIHRoaXMgZG9lcyBub3Qgc3luY2hyb25pemUgYmVjYXVzZSBub3RoaW5nIGNhbiBtb2RpZnkgb3VyIHN0YXRlIGF0IHRoaXMgdGltZQogICAgICAgIGFmdGVyQ29tcGxldGlvbihpbnRlcnBvc2VkU3luY0xpc3QpOwogICAgICAgIGFmdGVyQ29tcGxldGlvbihzeW5jTGlzdCk7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIGFmdGVyQ29tcGxldGlvbihMaXN0IHN5bmNzKSB7CiAgICAgICAgZm9yIChJdGVyYXRvciBpID0gc3luY3MuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7KSB7CiAgICAgICAgICAgIFN5bmNocm9uaXphdGlvbiBzeW5jaCA9IChTeW5jaHJvbml6YXRpb24pIGkubmV4dCgpOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgc3luY2guYWZ0ZXJDb21wbGV0aW9uKHN0YXR1cyk7CiAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBsb2cud2FybigiVW5leHBlY3RlZCBleGNlcHRpb24gZnJvbSBhZnRlckNvbXBsZXRpb247IGNvbnRpbnVpbmciLCBlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHZvaWQgZW5kUmVzb3VyY2VzKCkgewogICAgICAgIGVuZFJlc291cmNlcyhhY3RpdmVYYVJlc291cmNlcyk7CiAgICAgICAgZW5kUmVzb3VyY2VzKHN1c3BlbmRlZFhhUmVzb3VyY2VzKTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgZW5kUmVzb3VyY2VzKElkZW50aXR5SGFzaE1hcDxYQVJlc291cmNlLCBUcmFuc2FjdGlvbkJyYW5jaD4gcmVzb3VyY2VNYXApIHsKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICBYQVJlc291cmNlIHhhUmVzOwogICAgICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyOwogICAgICAgICAgICBpbnQgZmxhZ3M7CiAgICAgICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICAgICAgU2V0IGVudHJ5U2V0ID0gcmVzb3VyY2VNYXAuZW50cnlTZXQoKTsKICAgICAgICAgICAgICAgIGlmIChlbnRyeVNldC5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBNYXAuRW50cnkgZW50cnkgPSAoTWFwLkVudHJ5KSBlbnRyeVNldC5pdGVyYXRvcigpLm5leHQoKTsKICAgICAgICAgICAgICAgIHhhUmVzID0gKFhBUmVzb3VyY2UpIGVudHJ5LmdldEtleSgpOwogICAgICAgICAgICAgICAgbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgZW50cnkuZ2V0VmFsdWUoKTsKICAgICAgICAgICAgICAgIGZsYWdzID0gKHN0YXR1cyA9PSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSykgPyBYQVJlc291cmNlLlRNRkFJTCA6IFhBUmVzb3VyY2UuVE1TVUNDRVNTOwogICAgICAgICAgICAgICAgcmVzb3VyY2VNYXAucmVtb3ZlKHhhUmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgeGFSZXMuZW5kKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgZmxhZ3MpOwogICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICBsb2cud2FybigiRXJyb3IgZW5kaW5nIGFzc29jaWF0aW9uIGZvciBYQVJlc291cmNlICIgKyB4YVJlcyArICI7IHRyYW5zYWN0aW9uIHdpbGwgcm9sbCBiYWNrLiBYQSBlcnJvciBjb2RlOiAiICsgZS5lcnJvckNvZGUsIGUpOwogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19NQVJLRURfUk9MTEJBQ0s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIHJvbGxiYWNrUmVzb3VyY2VzKExpc3Q8VHJhbnNhY3Rpb25CcmFuY2g+IHJtcykgdGhyb3dzIFN5c3RlbUV4Y2VwdGlvbiB7CiAgICAgICAgU3lzdGVtRXhjZXB0aW9uIGNhdXNlID0gbnVsbDsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJtcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKICAgICAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGkubmV4dCgpOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLnJvbGxiYWNrKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKCJVbmV4cGVjdGVkIGV4Y2VwdGlvbiByb2xsaW5nIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCdzIG5vdCBzZXQgdGhlIGNhdXNlIGhlcmUKICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgcm9sbGVkIGJhY2sgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHdpdGggcm9sbGJhY2siLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFFUl9OT1RBCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRkFJTCkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3Qgc2V0IHRoZSBjYXVzZSBoZXJlIGJlY2F1c2Ugd2UgZXhwZWN0IHRoZSB0cmFuc2FjdGlvbiB0byBiZSByb2xsZWQgYmFjayBldmVudHVhbGx5CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZvciBSTUZBSUwsIGl0IG1lYW5zIHJlc291cmNlIHVuYXZhaWxhYmxlIHRlbXBvcmFyaWx5LiAgCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvIHdlIG5lZWQga2VlcCBzZW5kaW5nIHJlcXVlc3QgdG8gcmVzb3VyY2UgdG8gbWFrZSBzdXJlIHRoZSByb2xsIGJhY2sgY29tcGxldGVzPwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IG5ldyBTeXN0ZW1FeGNlcHRpb24oZS5lcnJvckNvZGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHJvbGxpbmcgYmFjayIpLmluaXRDYXVzZShlKTsgICAgICAgICAgICAKICAgICAgICB9ICAgICAgICAgICAgCgogICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewogICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s7CiAgICAgICAgfQogICAgICAgIGlmIChjYXVzZSAhPSBudWxsKSB7CiAgICAgICAgICAgIHRocm93IGNhdXNlOwogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIHZvaWQgcm9sbGJhY2tSZXNvdXJjZXNEdXJpbmdDb21taXQoTGlzdDxUcmFuc2FjdGlvbkJyYW5jaD4gcm1zLCBib29sZWFuIGV2ZXJSYikgdGhyb3dzIEhldXJpc3RpY01peGVkRXhjZXB0aW9uLCBSb2xsYmFja0V4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICBYQUV4Y2VwdGlvbiBjYXVzZSA9IG51bGw7CiAgICAgICAgYm9vbGVhbiBldmVyUm9sbGVkYmFjayA9IGV2ZXJSYjsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJtcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKICAgICAgICAgICAgICAgIFRyYW5zYWN0aW9uQnJhbmNoIG1hbmFnZXIgPSAoVHJhbnNhY3Rpb25CcmFuY2gpIGkubmV4dCgpOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLnJvbGxiYWNrKG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgZXZlclJvbGxlZGJhY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0J3Mgbm90IHNldCB0aGUgY2F1c2UgaGVyZSBhcyB0aGUgcmVzdWx0aW5nIGJlaGF2aW9yIGlzIHNhbWUgYXMgcmVxdWVzdGVkIGJlaGF2aW9yCiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSByb2xsZWQgYmFjayAiICsgbWFuYWdlci5nZXRDb21taXR0ZXIoKSArICI7IGNvbnRpbnVpbmcgd2l0aCByb2xsYmFjayIsIGUpOwogICAgICAgICAgICAgICAgICAgICAgICBldmVyUm9sbGVkYmFjayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcigiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSBjb21taXR0ZWQgYW5kIHJvbGxlZCBiYWNrICIgKyBtYW5hZ2VyLmdldENvbW1pdHRlcigpICsgIjsgY29udGludWluZyB3aXRoIHJvbGxiYWNrIiwgZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlclJvbGxlZGJhY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUkNPTSkgewogICAgICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkICIgKyBtYW5hZ2VyLmdldENvbW1pdHRlcigpICsgIjsgY29udGludWluZyB3aXRoIHJvbGxiYWNrIiwgZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBRVJfUk1GQUlMKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFhBRXhjZXB0aW9uLlhBX1JCUk9MTEJBQ0sgZHVyaW5nIGNvbW1pdC9yb2xsYmFjaywgdGh1cyBSb2xsYmFja0V4Y2VwdGlvbiBpcyBleHBlY3RlZAogICAgICAgICAgICAgICAgICAgICAgICAvLyBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIG1lYW5zIHRyYW5zYWN0aW9uIGJyYW5jaCBlcnJvciBhbmQgdHJhbnNhY3Rpb24gaGFzIGJlZW4gcm9sbGVkIGJhY2sKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0J3Mgbm90IHNldCB0aGUgY2F1c2UgaGVyZSBiZWNhdXNlIHdlIGV4cGVjdCB0aGUgdHJhbnNhY3Rpb24gdG8gYmUgcm9sbGVkIGJhY2sgZXZlbnR1YWxseQogICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBmb3IgUk1GQUlMLCBpdCBtZWFucyByZXNvdXJjZSB1bmF2YWlsYWJsZSB0ZW1wb3JhcmlseS4gIAogICAgICAgICAgICAgICAgICAgICAgICAvLyBkbyB3ZSBuZWVkIGtlZXAgc2VuZGluZyByZXF1ZXN0IHRvIHJlc291cmNlIHRvIG1ha2Ugc3VyZSB0aGUgcm9sbCBiYWNrIGNvbXBsZXRlcz8KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKFhBRXhjZXB0aW9uIGUpIHsKICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiU3lzdGVtIGVycm9yIGR1cmluZyBjb21taXQvcm9sbGluZyBiYWNrIikuaW5pdENhdXNlKGUpOyAgICAgICAgICAgIAogICAgICAgIH0KICAgICAgICAKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19ST0xMRURCQUNLOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAoY2F1c2UgPT0gbnVsbCkgewogICAgICAgICAgICB0aHJvdyAoUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBSb2xsYmFja0V4Y2VwdGlvbigiVW5hYmxlIHRvIGNvbW1pdDogdHJhbnNhY3Rpb24gbWFya2VkIGZvciByb2xsYmFjayIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSQ09NICYmIGV2ZXJSb2xsZWRiYWNrKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiSGV1cmlzdGljTWl4ZWQgZXJyb3IgZHVyaW5nIGNvbW1pdC9yb2xsaW5nIGJhY2siKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiSGV1cmlzdGljTWl4ZWQgZXJyb3IgZHVyaW5nIGNvbW1pdC9yb2xsaW5nIGJhY2siKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiU3lzdGVtIEVycm9yIGR1cmluZyBjb21taXQvcm9sbGluZyBiYWNrIikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSAKICAgICAgICB9CiAgICB9CiAgICAKICAgIHByaXZhdGUgdm9pZCBjb21taXRSZXNvdXJjZShUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyKSB0aHJvd3MgUm9sbGJhY2tFeGNlcHRpb24sIEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uLCBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uewogICAgICAgIFhBRXhjZXB0aW9uIGNhdXNlID0gbnVsbDsKICAgICAgICB0cnkgewogICAgICAgICAgICB0cnkgewoKICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuY29tbWl0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSwgdHJ1ZSk7CiAgICAgICAgICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBTdGF0dXMuU1RBVFVTX0NPTU1JVFRFRDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewogICAgICAgICAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gU3RhdHVzLlNUQVRVU19ST0xMRURCQUNLOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiAoZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwogICAgICAgICAgICAgICAgICAgIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkuZm9yZ2V0KG1hbmFnZXIuZ2V0QnJhbmNoSWQoKSk7CiAgICAgICAgICAgICAgICAgICAgLy90aHJvdyAoSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIG9uZS1waGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJNSVgpIHsKICAgICAgICAgICAgICAgICAgICBjYXVzZSA9IGU7CiAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIG9uZS1waGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJDT00pIHsKICAgICAgICAgICAgICAgICAgICAvLyBsZXQncyBub3QgdGhyb3cgYW4gZXhjZXB0aW9uIGFzIHRoZSB0cmFuc2FjdGlvbiBoYXMgYmVlbiBjb21taXR0ZWQKICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSBjb21taXR0ZWQiKTsKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9SQlJPTExCQUNLIAogICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIAogICAgICAgICAgICAgICAgICAgICAgICB8fCBlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEpIHsKICAgICAgICAgICAgICAgICAgICAvLyBQZXIgWEEgc3BlYywgWEFFeGNlcHRpb24uWEFFUl9STUVSUiBmcm9tIGNvbW1pdCBtZWFucyBBbiBlcnJvciBvY2N1cnJlZCBpbiAKICAgICAgICAgICAgICAgICAgICAvLyBjb21taXR0aW5nIHRoZSB3b3JrIHBlcmZvcm1lZCBvbiBiZWhhbGYgb2YgdGhlIHRyYW5zYWN0aW9uIGJyYW5jaCAKICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdGhlIGJyYW5jaNVzIHdvcmsgaGFzIGJlZW4gcm9sbGVkIGJhY2suIAogICAgICAgICAgICAgICAgICAgIC8vIFhBRXhjZXB0aW9uLlhBRVJfTk9UQTogIHNzdW1lIHRoZSBEQiB0b29rIGEgdW5pbGF0ZXJhbCByb2xsYmFjayBkZWNpc2lvbiBhbmQgZm9yZ290IHRoZSB0cmFuc2FjdGlvbgogICAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKCJUcmFuc2FjdGlvbiBoYXMgYmVlbiByb2xsZWQgYmFjayIpOwogICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAvLyB0aHJvdyAoUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIG9uZS1waGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKICAgICAgICAgICAgICAgICAgICAvL3Rocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyBvbmUtcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEpIHsKICAgICAgICAgICAgICAgIC8vIE5PVEEgaW4gcmVzcG9uc2UgdG8gZm9yZ2V0LCBtZWFucyB0aGUgcmVzb3VyY2UgYWxyZWFkeSBmb3Jnb3QgdGhlIHRyYW5zYWN0aW9uCiAgICAgICAgICAgICAgICAvLyBpZ25vcmUKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyBvbmUgcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGlmIChjYXVzZSAhPSBudWxsKSB7CiAgICAgICAgICAgIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUlJCKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9SQlJPTExCQUNLIAogICAgICAgICAgICAgICAgICAgIHx8IGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX1JNRVJSIAogICAgICAgICAgICAgICAgICAgIHx8IGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEpIHsKICAgICAgICAgICAgICAgIHRocm93IChSb2xsYmFja0V4Y2VwdGlvbikgbmV3IFJvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAoU3lzdGVtRXhjZXB0aW9uKSBuZXcgU3lzdGVtRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gCiAgICAgICAgfQogICAgfQogICAgCiAgICBwcml2YXRlIHZvaWQgY29tbWl0UmVzb3VyY2VzKExpc3Q8VHJhbnNhY3Rpb25CcmFuY2g+IHJtcykgdGhyb3dzIEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uLCBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbiwgU3lzdGVtRXhjZXB0aW9uIHsKICAgICAgICAvL1RPRE8gdGhlcmUncyBzb21lIGxvZ2ljIHJlbW92ZWQgYWJvdXQgZGVhbGluZyB3aXRoIGEgaGV1cmlzdGljIHJvbGxiYWNrIG9uIHRoZSBmaXJzdCByZXNvdXJjZS4KICAgICAgICBDb21taXRUYXNrIGNvbW1pdFRhc2sgPSBuZXcgQ29tbWl0VGFzayh4aWQsIHJtcywgbG9nTWFyaywgcmV0cnlTY2hlZHVsZXIsIHR4bkxvZyk7CiAgICAgICAgc3luY2hyb25pemVkICh0aGlzKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzsKICAgICAgICB9CiAgICAgICAgY29tbWl0VGFzay5ydW4oKTsKICAgICAgICBzeW5jaHJvbml6ZWQgKHRoaXMpIHsKICAgICAgICAgICAgc3RhdHVzID0gY29tbWl0VGFzay5nZXRTdGF0dXMoKTsKICAgICAgICB9CiAgICAgICAgWEFFeGNlcHRpb24gY2F1c2UgPSBjb21taXRUYXNrLmdldENhdXNlKCk7CiAgICAgICAgaWYgKGNhdXNlICE9IG51bGwpIHsKICAgICAgICAgICAgaWYgKGNhdXNlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbikgbmV3IEhldXJpc3RpY1JvbGxiYWNrRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQikgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewogICAgICAgICAgICAgICAgdGhyb3cgKEhldXJpc3RpY01peGVkRXhjZXB0aW9uKSBuZXcgSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCgovLyAgICAgICAgWEFFeGNlcHRpb24gY2F1c2UgPSBudWxsOwovLyAgICAgICAgYm9vbGVhbiBldmVyY29tbWl0ID0gZmFsc2U7Ci8vICAgICAgICB0cnkgewovLyAgICAgICAgICAgIGZvciAoSXRlcmF0b3IgaSA9IHJtcy5pdGVyYXRvcigpOyBpLmhhc05leHQoKTspIHsKLy8gICAgICAgICAgICAgICAgVHJhbnNhY3Rpb25CcmFuY2ggbWFuYWdlciA9IChUcmFuc2FjdGlvbkJyYW5jaCkgaS5uZXh0KCk7Ci8vICAgICAgICAgICAgICAgIHRyeSB7Ci8vICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmNvbW1pdChtYW5hZ2VyLmdldEJyYW5jaElkKCksIGZhbHNlKTsKLy8gICAgICAgICAgICAgICAgICAgIGV2ZXJjb21taXQgPSB0cnVlOwovLyAgICAgICAgICAgICAgICB9IGNhdGNoIChYQUV4Y2VwdGlvbiBlKSB7Ci8vICAgICAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGNvbW1pdHRpbmcgIiArIG1hbmFnZXIuZ2V0Q29tbWl0dGVyKCkgKyAiOyBjb250aW51aW5nIHRvIGNvbW1pdCBvdGhlciBSTXMiLCBlKTsKLy8KLy8gICAgICAgICAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSUkIpIHsKLy8gICAgICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbygiVHJhbnNhY3Rpb24gaGFzIGJlZW4gaGV1cmlzdGljYWxseSByb2xsZWQgYmFjayIpOwovLyAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKLy8gICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwovLyAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSTUlYKSB7Ci8vICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIGFuZCByb2xsZWQgYmFjayIpOwovLyAgICAgICAgICAgICAgICAgICAgICAgIGNhdXNlID0gZTsKLy8gICAgICAgICAgICAgICAgICAgICAgICBldmVyY29tbWl0ID0gdHJ1ZTsKLy8gICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VyLmdldENvbW1pdHRlcigpLmZvcmdldChtYW5hZ2VyLmdldEJyYW5jaElkKCkpOwovLyAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQV9IRVVSQ09NKSB7Ci8vICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0J3Mgbm90IHRocm93IGFuIGV4Y2VwdGlvbiBhcyB0aGUgdHJhbnNhY3Rpb24gaGFzIGJlZW4gY29tbWl0dGVkCi8vICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmluZm8oIlRyYW5zYWN0aW9uIGhhcyBiZWVuIGhldXJpc3RpY2FsbHkgY29tbWl0dGVkIik7Ci8vICAgICAgICAgICAgICAgICAgICAgICAgZXZlcmNvbW1pdCA9IHRydWU7Ci8vICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlci5nZXRDb21taXR0ZXIoKS5mb3JnZXQobWFuYWdlci5nZXRCcmFuY2hJZCgpKTsKLy8gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7Ci8vICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2UgPSBlOwovLyAgICAgICAgICAgICAgICAgICAgfQovLyAgICAgICAgICAgICAgICB9Ci8vICAgICAgICAgICAgfQovLyAgICAgICAgfSBjYXRjaCAoWEFFeGNlcHRpb24gZSkgewovLyAgICAgICAgICAgIGlmIChlLmVycm9yQ29kZSA9PSBYQUV4Y2VwdGlvbi5YQUVSX05PVEEpIHsKLy8gICAgICAgICAgICAgICAgLy8gTk9UQSBpbiByZXNwb25zZSB0byBmb3JnZXQsIG1lYW5zIHRoZSByZXNvdXJjZSBhbHJlYWR5IGZvcmdvdCB0aGUgdHJhbnNhY3Rpb24KLy8gICAgICAgICAgICAgICAgLy8gaWdub3JlCi8vICAgICAgICAgICAgfSBlbHNlIHsKLy8gICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoZSk7Ci8vICAgICAgICAgICAgfQovLyAgICAgICAgfQovLyAgICAgICAgLy9pZiBhbGwgcmVzb3VyY2VzIHdlcmUgcmVhZCBvbmx5LCB3ZSBkaWRuJ3Qgd3JpdGUgYSBwcmVwYXJlIHJlY29yZC4KLy8gICAgICAgIGlmICghcm1zLmlzRW1wdHkoKSkgewovLyAgICAgICAgICAgIHRyeSB7Ci8vICAgICAgICAgICAgICAgIHR4bkxvZy5jb21taXQoeGlkLCBsb2dNYXJrKTsKLy8gICAgICAgICAgICB9IGNhdGNoIChMb2dFeGNlcHRpb24gZSkgewovLyAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIGxvZ2dpbmcgY29tbWl0IGNvbXBsZXRpb24gZm9yIHhpZCAiICsgeGlkLCBlKTsKLy8gICAgICAgICAgICAgICAgdGhyb3cgKFN5c3RlbUV4Y2VwdGlvbikgbmV3IFN5c3RlbUV4Y2VwdGlvbigiVW5leHBlY3RlZCBlcnJvciBsb2dnaW5nIGNvbW1pdCBjb21wbGV0aW9uIGZvciB4aWQgIiArIHhpZCkuaW5pdENhdXNlKGUpOwovLyAgICAgICAgICAgIH0KLy8gICAgICAgIH0KLy8gICAgICAgIHN5bmNocm9uaXplZCAodGhpcykgewovLyAgICAgICAgICAgIHN0YXR1cyA9IFN0YXR1cy5TVEFUVVNfQ09NTUlUVEVEOwovLyAgICAgICAgfQovLyAgICAgICAgaWYgKGNhdXNlICE9IG51bGwpIHsKLy8gICAgICAgICAgICBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQiAmJiAhZXZlcmNvbW1pdCkgewovLyAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljUm9sbGJhY2tFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNSb2xsYmFja0V4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwovLyAgICAgICAgICAgIH0gZWxzZSBpZiAoY2F1c2UuZXJyb3JDb2RlID09IFhBRXhjZXB0aW9uLlhBX0hFVVJSQiAmJiBldmVyY29tbWl0KSB7Ci8vICAgICAgICAgICAgICAgIHRocm93IChIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbikgbmV3IEhldXJpc3RpY01peGVkRXhjZXB0aW9uKCJFcnJvciBkdXJpbmcgdHdvIHBoYXNlIGNvbW1pdCIpLmluaXRDYXVzZShjYXVzZSk7Ci8vICAgICAgICAgICAgfSBlbHNlIGlmIChjYXVzZS5lcnJvckNvZGUgPT0gWEFFeGNlcHRpb24uWEFfSEVVUk1JWCkgewovLyAgICAgICAgICAgICAgICB0aHJvdyAoSGV1cmlzdGljTWl4ZWRFeGNlcHRpb24pIG5ldyBIZXVyaXN0aWNNaXhlZEV4Y2VwdGlvbigiRXJyb3IgZHVyaW5nIHR3byBwaGFzZSBjb21taXQiKS5pbml0Q2F1c2UoY2F1c2UpOwovLyAgICAgICAgICAgIH0gZWxzZSB7Ci8vICAgICAgICAgICAgICAgIHRocm93IChTeXN0ZW1FeGNlcHRpb24pIG5ldyBTeXN0ZW1FeGNlcHRpb24oIkVycm9yIGR1cmluZyB0d28gcGhhc2UgY29tbWl0IikuaW5pdENhdXNlKGNhdXNlKTsKLy8gICAgICAgICAgICB9Ci8vICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGdldFN0YXRlU3RyaW5nKGludCBzdGF0dXMpIHsKICAgICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQUNUSVZFOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfQUNUSVZFIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1BSRVBBUklORzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1BSRVBBUklORyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19QUkVQQVJFRDoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1BSRVBBUkVEIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX01BUktFRF9ST0xMQkFDSzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX01BUktFRF9ST0xMQkFDSyI7CiAgICAgICAgICAgIGNhc2UgU3RhdHVzLlNUQVRVU19ST0xMSU5HX0JBQ0s6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19ST0xMSU5HX0JBQ0siOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQ09NTUlUVElORzoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX0NPTU1JVFRJTkciOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfQ09NTUlUVEVEOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfQ09NTUlUVEVEIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX1JPTExFREJBQ0s6CiAgICAgICAgICAgICAgICByZXR1cm4gIlNUQVRVU19ST0xMRURCQUNLIjsKICAgICAgICAgICAgY2FzZSBTdGF0dXMuU1RBVFVTX05PX1RSQU5TQUNUSU9OOgogICAgICAgICAgICAgICAgcmV0dXJuICJTVEFUVVNfTk9fVFJBTlNBQ1RJT04iOwogICAgICAgICAgICBjYXNlIFN0YXR1cy5TVEFUVVNfVU5LTk9XTjoKICAgICAgICAgICAgICAgIHJldHVybiAiU1RBVFVTX1VOS05PV04iOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKCk7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhPYmplY3Qgb2JqKSB7CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIFRyYW5zYWN0aW9uSW1wbCkgewogICAgICAgICAgICBUcmFuc2FjdGlvbkltcGwgb3RoZXIgPSAoVHJhbnNhY3Rpb25JbXBsKSBvYmo7CiAgICAgICAgICAgIHJldHVybiB4aWQuZXF1YWxzKG90aGVyLnhpZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KCiAgICAvL3doZW4gdXNlZCBmcm9tIHJlY292ZXJ5LCBkbyBub3QgYWRkIG1hbmFnZXIgdG8gYWN0aXZlIG9yIHN1c3BlbmRlZCByZXNvdXJjZSBtYXBzLgogICAgLy8gVGhlIHhhcmVzb3VyY2VzIGhhdmUgYWxyZWFkeSBiZWVuIGVuZGVkIHdpdGggVE1TVUNDRVNTLgogICAgcHVibGljIFRyYW5zYWN0aW9uQnJhbmNoIGFkZEJyYW5jaFhpZChYQVJlc291cmNlIHhhUmVzLCBYaWQgYnJhbmNoSWQpIHsKICAgICAgICBUcmFuc2FjdGlvbkJyYW5jaCBtYW5hZ2VyID0gbmV3IFRyYW5zYWN0aW9uQnJhbmNoKHhhUmVzLCBicmFuY2hJZCk7CiAgICAgICAgcmVzb3VyY2VNYW5hZ2Vycy5hZGQobWFuYWdlcik7CiAgICAgICAgcmV0dXJuIG1hbmFnZXI7CiAgICB9CgogICAgc3RhdGljIGNsYXNzIFRyYW5zYWN0aW9uQnJhbmNoIGltcGxlbWVudHMgVHJhbnNhY3Rpb25CcmFuY2hJbmZvIHsKICAgICAgICBwcml2YXRlIGZpbmFsIFhBUmVzb3VyY2UgY29tbWl0dGVyOwogICAgICAgIHByaXZhdGUgZmluYWwgWGlkIGJyYW5jaElkOwoKICAgICAgICBwdWJsaWMgVHJhbnNhY3Rpb25CcmFuY2goWEFSZXNvdXJjZSB4YVJlcywgWGlkIGJyYW5jaElkKSB7CiAgICAgICAgICAgIGNvbW1pdHRlciA9IHhhUmVzOwogICAgICAgICAgICB0aGlzLmJyYW5jaElkID0gYnJhbmNoSWQ7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgWEFSZXNvdXJjZSBnZXRDb21taXR0ZXIoKSB7CiAgICAgICAgICAgIHJldHVybiBjb21taXR0ZXI7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgWGlkIGdldEJyYW5jaElkKCkgewogICAgICAgICAgICByZXR1cm4gYnJhbmNoSWQ7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgU3RyaW5nIGdldFJlc291cmNlTmFtZSgpIHsKICAgICAgICAgICAgaWYgKGNvbW1pdHRlciBpbnN0YW5jZW9mIE5hbWVkWEFSZXNvdXJjZSkgewogICAgICAgICAgICAgICAgcmV0dXJuICgoTmFtZWRYQVJlc291cmNlKSBjb21taXR0ZXIpLmdldE5hbWUoKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIGlmIGl0IGlzbid0IGEgbmFtZWQgcmVzb3VyY2Ugc2hvdWxkIHdlIHJlYWxseSBzdG9wIGFsbCBwcm9jZXNzaW5nIGhlcmUhCiAgICAgICAgICAgICAgICAvLyBNYXliZSB0aGlzIHdvdWxkIGJlIGJldHRlciB0byBoYW5kbGUgZWxzZSB3aGVyZSBhbmQgZG8gd2UgcmVhbGx5IHdhbnQgdG8gcHJldmVudCBhbGwgcHJvY2Vzc2luZyBvZiB0cmFuc2FjdGlvbnM/CiAgICAgICAgICAgICAgICBsb2cuZXJyb3IoIlBsZWFzZSBjb3JyZWN0IHRoZSBpbnRlZ3JhdGlvbiBhbmQgc3VwcGx5IGEgTmFtZWRYQVJlc291cmNlIiwgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigiQ2Fubm90IGxvZyB0cmFuc2FjdGlvbnMgYXMgIiArIGNvbW1pdHRlciArICIgaXMgbm90IGEgTmFtZWRYQVJlc291cmNlLiIpKTsKICAgICAgICAgICAgICAgIHJldHVybiBjb21taXR0ZXIudG9TdHJpbmcoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIFhpZCBnZXRCcmFuY2hYaWQoKSB7CiAgICAgICAgICAgIHJldHVybiBicmFuY2hJZDsKICAgICAgICB9CiAgICB9CgoKfQo=