cGFja2FnZSBvcmcuYXBhY2hlLmpjcy5lbmdpbmUubWVtb3J5LmFyYzsKCi8qCiAqIENvcHlyaWdodCAyMDAxLTIwMDQgVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKQogKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogKgogKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqLwoKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLlNlcmlhbGl6YWJsZTsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CgppbXBvcnQgRURVLm9zd2Vnby5jcy5kbC51dGlsLmNvbmN1cnJlbnQuQ29uY3VycmVudEhhc2hNYXA7CgppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmxvZ2dpbmcuTG9nOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmxvZ2dpbmcuTG9nRmFjdG9yeTsKCmltcG9ydCBvcmcuYXBhY2hlLmpjcy5lbmdpbmUuQ2FjaGVFbGVtZW50OwppbXBvcnQgb3JnLmFwYWNoZS5qY3MuZW5naW5lLmNvbnRyb2wuQ29tcG9zaXRlQ2FjaGU7CmltcG9ydCBvcmcuYXBhY2hlLmpjcy5lbmdpbmUuYmVoYXZpb3IuSUNhY2hlRWxlbWVudDsKaW1wb3J0IG9yZy5hcGFjaGUuamNzLmVuZ2luZS5tZW1vcnkuQWJzdHJhY3RNZW1vcnlDYWNoZTsKaW1wb3J0IG9yZy5hcGFjaGUuamNzLmVuZ2luZS5tZW1vcnkudXRpbC5Eb3VibGVMaW5rZWRMaXN0OwppbXBvcnQgb3JnLmFwYWNoZS5qY3MuZW5naW5lLm1lbW9yeS51dGlsLk1lbW9yeUVsZW1lbnREZXNjcmlwdG9yOwppbXBvcnQgb3JnLmFwYWNoZS5qY3MuZW5naW5lLnN0YXRzLlN0YXRFbGVtZW50OwppbXBvcnQgb3JnLmFwYWNoZS5qY3MuZW5naW5lLnN0YXRzLlN0YXRzOwppbXBvcnQgb3JnLmFwYWNoZS5qY3MuZW5naW5lLnN0YXRzLmJlaGF2aW9yLklTdGF0RWxlbWVudDsKaW1wb3J0IG9yZy5hcGFjaGUuamNzLmVuZ2luZS5zdGF0cy5iZWhhdmlvci5JU3RhdHM7CgovKioKICogIFRoaXMgaXMgYSByb3VnaCBpbXBsbWVudGF0aW9uIG9mIGFuIGFkYXB0aXZlIHJlcGxhY2VtZW50IGNhY2hlLgogKiAgQVJDIGlzIGEgaHlicmlkIExGVSAvIExSVSB0aGF0IGFkYXB0cyB0byB1c2VyIGJlaGF2aW9yLgogKgogKiAgU2VlIHRoZSBBUkMgbWV0aG9kIGZvciBtb3JlIGRldGFpbCBvbiBob3cgdGhlIGFsZ29yaXRobSB3b3Jrcy4KICoKICogIEBzZWUgIGh0dHA6Ly93d3cuYWxtYWRlbi5pYm0uY29tL1N0b3JhZ2VTeXN0ZW1zL2F1dG9ub21pY19zdG9yYWdlL0FSQy9pbmRleC5zaHRtbAogKi8KcHVibGljIGNsYXNzIEFSQ01lbW9yeUNhY2hlCiAgICBleHRlbmRzIEFic3RyYWN0TWVtb3J5Q2FjaGUKewoKICBwcml2YXRlIGZpbmFsIHN0YXRpYyBMb2cgbG9nID0KICAgICAgTG9nRmFjdG9yeS5nZXRMb2coQVJDTWVtb3J5Q2FjaGUuY2xhc3MpOwoKICBpbnRbXSBsb2MgPSBuZXcgaW50WzBdOwoKICAvLyBtYXhpbXVtIHNpemUKICBpbnQgYyA9IDA7CgogIERvdWJsZUxpbmtlZExpc3QgVDEgPSBuZXcgRG91YmxlTGlua2VkTGlzdCgpOwogIERvdWJsZUxpbmtlZExpc3QgVDIgPSBuZXcgRG91YmxlTGlua2VkTGlzdCgpOwogIERvdWJsZUxpbmtlZExpc3QgQjEgPSBuZXcgRG91YmxlTGlua2VkTGlzdCgpOwogIERvdWJsZUxpbmtlZExpc3QgQjIgPSBuZXcgRG91YmxlTGlua2VkTGlzdCgpOwoKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgX1QxXyA9IDE7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgaW50IF9UMl8gPSAyOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGludCBfQjFfID0gMzsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgX0IyXyA9IDQ7CgogIC8vIGlkZWFsIHNpemUgb2YgVDEKICBpbnQgdGFyZ2V0X1QxID0gMDsKCiAgQ29uY3VycmVudEhhc2hNYXAgbWFwID0gbmV3IENvbmN1cnJlbnRIYXNoTWFwKCk7CgogIGludCBjbnQgPSAwOwoKICBpbnQgaGl0Q250ID0gMDsKICBpbnQgbWlzc0NudCA9IDA7CiAgaW50IHB1dENudCA9IDA7CgogIHB1YmxpYyBBUkNNZW1vcnlDYWNoZSgpCiAgewogICAgbG9nLmRlYnVnKCJMb2FkaW5nIEFyYyIpOwogIH0KCiAgcHVibGljIE9iamVjdFtdIGdldEtleUFycmF5KCkKICB7CiAgICByZXR1cm4gbnVsbDsKICB9CgogIHB1YmxpYyBJQ2FjaGVFbGVtZW50IGdldFF1aWV0KFNlcmlhbGl6YWJsZSBrZXkpIHRocm93cyBJT0V4Y2VwdGlvbgogIHsKICAgIHJldHVybiBnZXQoa2V5KTsKICB9CgogIC8qKgogICAqICBGb3IgcG9zdCByZWZsZWN0aW9uIGNyZWF0aW9uIGluaXRpYWxpemF0aW9uCiAgICoKICAgKkBwYXJhbSAgaHViCiAgICovCiAgcHVibGljIHN5bmNocm9uaXplZCB2b2lkIGluaXRpYWxpemUoQ29tcG9zaXRlQ2FjaGUgaHViKQogIHsKICAgIHN1cGVyLmluaXRpYWxpemUoaHViKTsKICAgIGMgPSB0aGlzLmNhdHRyLmdldE1heE9iamVjdHMoKTsgLy8gLyAyOwogICAgdGFyZ2V0X1QxID0gYyAvIDI7CiAgICBsb2cuaW5mbygiaW5pdGlhbGl6ZWQgTFJVTWVtb3J5Q2FjaGUgZm9yICIgKyBjYWNoZU5hbWUpOwogIH0KCiAgcHVibGljIElDYWNoZUVsZW1lbnQgZ2V0KFNlcmlhbGl6YWJsZSBrZXkpIHRocm93cyBJT0V4Y2VwdGlvbgogIHsKICAgIENhY2hlRWxlbWVudCBjZSA9IG5ldyBDYWNoZUVsZW1lbnQoY2FjaGVOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoU2VyaWFsaXphYmxlKSBrZXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bGwpOwoKICAgIElDYWNoZUVsZW1lbnQgaWNlID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGljZSA9IEFSQyhjZSwgdHJ1ZSk7CiAgICB9IGNhdGNoKCBFeGNlcHRpb24gZSApIHsKICAgICAgbG9nLmVycm9yKCBlICk7CiAgICB9CiAgICByZXR1cm4gaWNlOwogIH0KCiAgcHVibGljIHZvaWQgdXBkYXRlKElDYWNoZUVsZW1lbnQgY2UpCiAgewogICAgdHJ5IHsKICAgICAgQVJDKGNlLCBmYWxzZSk7CiAgICB9IGNhdGNoKCBFeGNlcHRpb24gZSApIHsKICAgICAgbG9nLmVycm9yKCBlICk7CiAgICB9CiAgfQoKICAvKioKICAgKiBUaGlzIGlzIHRoZSBwcmltYXJ5IG1ldGhvZCBmb3IgdGhlIEFSQy4gIEl0IGhhbmRsZXMgYm90aCBwdXRzIGFuZCBnZXRzLgogICAqIFRoZSBBUkMgaGFzIDQgbGlua2VkIGxpc3RzOiBUMSwgVDIsIEIxLCBhbmQgQjIuICBUaGUgJ1QnIGxpc3RzIGFyZSB0b3BzCiAgICogYW5kIHRoZSAnQicgbGlzdHMgYXJlIGJvdHRvbXMuICBCb3R0b20gbGlzdHMgZG8gbm90IGhvbGQgb2JqZWN0LCBvbmx5IGtleXMuCiAgICoKICAgKiBUaGUgVDEgbGlzdCBpcyBhbiBMUlUgKExlYXN0IFJlY2VudGx5IFVzZWQpIGxpc3QuICBUaGUgVDIgbGlzdCBpcyBhIG5lYXIKICAgKiBMRlUgKExlYXN0IEZyZXF1ZW50bHkgVXNlZCkgbGlzdC4KICAgKgogICAqIEFmdGVyIGl0ZW1zIGFyZSByZW1vdmVkIGZyb20gVDEgYW5kIFQyLCB0aGVpciBrZXlzIGFyZSBzdG9yZWQgaW4gQjEgYW5kIEIyLgogICAqIFRoZSBudW1iZXIgb2Yga2V5cyBpbiBCMSBhbmQgQjIgaXMgcmVzdHJpY3RlZCB0byB0aGUgbnVtYmVyIG9mIG1heCBpdGVtcy4KICAgKgogICAqIFdoZW4gdGhlcmUgaXMgYSBwdXQgb3IgYSBnZXQgZm9yIGFuIGl0ZW0gd2hvc2Uga2V5IGV4aXN0cyBvbiBvbmUgb2YgdGhlCiAgICogYm90dG9tIGxpc3RzLCB0aGUgbWF4aW11bSBudW1iZXIgb2YgaXRlbXMgaW4gVDEgaXMgYWRqdXN0ZWQuICBJZiB0aGUgaXRlbQogICAqIHdhcyBmb3VuZCBvbiBCMiAodGhlIGJvdHRvbSBMRlUgbGlzdCkgdGhlIG1heGltdW0gYWxsb3dlZCBpbiBUMSAodGhlIHRvcAogICAqIExSVSBsaXN0KSBpcyByZWR1Y2VkLiAgSWYgdGhlIGl0ZW0gaXMgZm91bmQgaW4gQjEgbGlzdCAodGhlIGJvdHRvbSBMUlUpIHRoZQogICAqIG1heGltdW0gYWxsb3dlZCBpbiBUMSBpcyBpbmNyZWFzZWQuCiAgICoKICAgKiBUaGUgbWF4aW11bSBhbGxvd2VkIGluIFQxIHdpbGwgbm90IGV4Y2VlZCB0aGUgbWF4U2l6ZS4gIFRoZSBtYXhpbXVtIGluIFQxCiAgICogYW5kIFQyIGNvbWJpbmVkIHdpbGwgbm90IGV4Y2VlZCB0aGUgbWF4U2l6ZS4gIFRoZSBtYXhpbXVtIG51bWJlciBvZiBlbGVtZW50cwogICAqIGFuZCBrZXlzIGFsbG93ZWQgaW4gYWxsIDQgbGlzdHMgd2lsbCBub3QgZXhjZWVkIHR3aWNlIHRoZSBtYXhpbXVtIHNpemUuCiAgICoKICAgKiBAcGFyYW0gY2UgSUNhY2hlRWxlbWVudAogICAqIEBwYXJhbSBpc0dldCBib29sZWFuCiAgICogQHJldHVybiBJQ2FjaGVFbGVtZW50CiAgICovCiAgcHVibGljIElDYWNoZUVsZW1lbnQgQVJDKElDYWNoZUVsZW1lbnQgY2UsIGJvb2xlYW4gaXNHZXQpCiAgewoKICAgIGNudCsrOwoKICAgIGlmIChjbnQgJSAxMDAwMCA9PSAwKQogICAgLy9pZiAoIHRydWUgKQogICAgewogICAgICBpZiAobG9nLmlzSW5mb0VuYWJsZWQoKSkKICAgICAgewogICAgICAgIFN0cmluZ0J1ZmZlciBidWYgPSBuZXcgU3RyaW5nQnVmZmVyKCk7CiAgICAgICAgYnVmLmFwcGVuZCgiXG4gY2Uua2V5KCkgPSAiICsgY2UuZ2V0S2V5KCkpOwogICAgICAgIGJ1Zi5hcHBlbmQoIlxuIGlzR2V0ID0gIiArIGlzR2V0KTsKICAgICAgICBidWYuYXBwZW5kKGdldFN0YXRzKCkpOwogICAgICAgIGxvZy5pbmZvKGJ1Zi50b1N0cmluZygpKTsKICAgICAgfQogICAgfQoKICAgIGlmICghaXNHZXQpCiAgICB7CiAgICAgIHB1dENudCsrOwogICAgfQoKICAgIEVsZW1lbnREZXNjcmlwdG9yIHRlbXAgPSAoRWxlbWVudERlc2NyaXB0b3IpIG1hcC5nZXQoY2UuZ2V0S2V5KCkpOwogICAgYm9vbGVhbiBpc0hpdCA9IHRydWU7CgogICAgaWYgKHRlbXAgIT0gbnVsbCkKICAgIHsKCiAgICAgIGlmIChpc0dldCkKICAgICAgewogICAgICAgIGhpdENudCsrOwogICAgICB9CgogICAgICBzd2l0Y2ggKHRlbXAubGlzdE51bSkKICAgICAgewogICAgICAgIGNhc2UgX1QxXzoKICAgICAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgbG9nLmRlYnVnKCJUMSIpOwogICAgICAgICAgfQoKICAgICAgICAgIGxvZy5kZWJ1ZygiVDEgdG8gVDIsIGJlZm9yZSByZW1vdmUgPSAiICsgVDEuc2l6ZSgpKTsKICAgICAgICAgIGJvb2xlYW4gc3RhdDEgPSBUMS5yZW1vdmUodGVtcCk7IC8vIG5lZWQgdG8gaW1wbGVtZW50IG91ciBvd24gbGlzdAogICAgICAgICAgbG9nLmRlYnVnKCJUMSB0byBUMiwgYWZ0ZXIgcmVtb3ZlID0gIiArIFQxLnNpemUoKSArICIgc3RhdCA9ICIgKyBzdGF0MSk7CgogICAgICAgICAgdGVtcC5saXN0TnVtID0gX1QyXzsKICAgICAgICAgIFQyLmFkZEZpcnN0KHRlbXApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgX1QyXzoKICAgICAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgbG9nLmRlYnVnKCJUMiIpOwogICAgICAgICAgfQoKICAgICAgICAgIHRlbXAubGlzdE51bSA9IF9UMl87CiAgICAgICAgICBUMi5tYWtlRmlyc3QodGVtcCk7CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSBfQjFfOgoKICAgICAgICAgIC8vIEIxIGhpdDogZmF2b3IgcmVjZW5jeQoKICAgICAgICAgIC8vIGFkYXB0IHRoZSB0YXJnZXQgc2l6ZQogICAgICAgICAgdGFyZ2V0X1QxID0gTWF0aC5taW4odGFyZ2V0X1QxICsgTWF0aC5tYXgoQjIuc2l6ZSgpIC8gQjEuc2l6ZSgpLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMpOwogICAgICAgICAgaWYgKGxvZy5pc0RlYnVnRW5hYmxlZCgpKQogICAgICAgICAgewogICAgICAgICAgICBsb2cuZGVidWcoIkIxLCB0YXJnZXRUMSA9ICIgKyB0YXJnZXRfVDEgKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoIWlzR2V0KQogICAgICAgICAgewogICAgICAgICAgICBpZiAobG9nLmlzRGVidWdFbmFibGVkKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBsb2cuZGVidWcoIkIxIGJlZm9yZSByZW1vdmUgPSAiICsgQjEuc2l6ZSgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBib29sZWFuIHN0YXQzID0gQjEucmVtb3ZlKHRlbXApOyAvLyBuZWVkIHRvIGltcGxlbWVudCBvdXIgb3duIGxpc3QKICAgICAgICAgICAgaWYgKGxvZy5pc0RlYnVnRW5hYmxlZCgpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgbG9nLmRlYnVnKCJCMSBhZnRlciByZW1vdmUgPSAiICsgQjEuc2l6ZSgpICsgIiBzdGF0ID0gIiArIHN0YXQzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXBsYWNlKHRlbXApOwogICAgICAgICAgICB0ZW1wLmxpc3ROdW0gPSBfVDJfOwogICAgICAgICAgICB0ZW1wLmNlID0gY2U7CiAgICAgICAgICAgIFQyLmFkZEZpcnN0KHRlbXApOyAvLyBzZWVuIHR3aWNlIHJlY2VudGx5LCBwdXQgb24gVDIKCiAgICAgICAgICB9CiAgICAgICAgICBlbHNlCiAgICAgICAgICB7CiAgICAgICAgICAgIC8vIGlmIHRoaXMgaXMganVzdCBhIGdldCwgdGhlbiBhZGp1c3QgdGhlIGNhY2hlCiAgICAgICAgICAgIC8vIGl0IGlzIGVzc2VudGlhbGx5IGEgbWlzcy4KICAgICAgICAgICAgdGVtcCA9IG51bGw7CiAgICAgICAgICAgIGhpdENudC0tOwogICAgICAgICAgICBtaXNzQ250Kys7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSBfQjJfOgoKICAgICAgICAgIC8vIEIyIGhpdDogZmF2b3IgZnJlcXVlbmN5CgogICAgICAgICAgLy8gYWRhcHQgdGhlIHRhcmdldCBzaXplCiAgICAgICAgICB0YXJnZXRfVDEgPSBNYXRoLm1heCh0YXJnZXRfVDEgLSBNYXRoLm1heChCMS5zaXplKCkgLyBCMi5zaXplKCksIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCk7CiAgICAgICAgICBpZiAobG9nLmlzRGVidWdFbmFibGVkKCkpCiAgICAgICAgICB7CiAgICAgICAgICAgIGxvZy5kZWJ1ZygiQjIsIHRhcmdldFQxID0gIiArIHRhcmdldF9UMSApOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICghaXNHZXQpCiAgICAgICAgICB7CiAgICAgICAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgIGxvZy5kZWJ1ZygiQjIgYmVmb3JlIHJlbW92ZSA9ICIgKyBCMi5zaXplKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJvb2xlYW4gc3RhdDQgPSBCMi5yZW1vdmUodGVtcCk7IC8vIG5lZWQgdG8gaW1wbGVtZW50IG91ciBvd24gbGlzdAogICAgICAgICAgICBpZiAobG9nLmlzRGVidWdFbmFibGVkKCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBsb2cuZGVidWcoIkIyIGFmdGVyIHJlbW92ZSA9ICIgKyBCMi5zaXplKCkgKyAiIHN0YXQgPSAiICsgc3RhdDQpOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXBsYWNlKHRlbXApOwogICAgICAgICAgICB0ZW1wLmxpc3ROdW0gPSBfVDJfOwogICAgICAgICAgICB0ZW1wLmNlID0gY2U7CiAgICAgICAgICAgIFQyLmFkZEZpcnN0KHRlbXApOyAvLyBzZWVuIHR3aWNlIHJlY2VudGx5LCBwdXQgb24gVDIKCiAgICAgICAgICAgIHJlcGxhY2UodGVtcCk7CiAgICAgICAgICB9CiAgICAgICAgICBlbHNlCiAgICAgICAgICB7CiAgICAgICAgICAgIC8vIGlmIHRoaXMgaXMganVzdCBhIGdldCwgdGhlbiBhZGp1c3QgdGhlIGNhY2hlCiAgICAgICAgICAgIC8vIGl0IGlzIGVzc2VudGlhbGx5IGEgbWlzcy4KICAgICAgICAgICAgdGVtcCA9IG51bGw7CiAgICAgICAgICAgIGhpdENudC0tOwogICAgICAgICAgICBtaXNzQ250Kys7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgLy8gd2FzIG51bGwKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgLyogcGFnZSBpcyBub3QgaW4gY2FjaGUgICovCgogICAgICBpc0hpdCA9IGZhbHNlOwogICAgICBpZiAoaXNHZXQpCiAgICAgIHsKICAgICAgICBtaXNzQ250Kys7CiAgICAgIH0KCiAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgewogICAgICAgIGxvZy5kZWJ1ZygiUGFnZSBpcyBub3QgaW4gY2FjaGUiKTsKICAgICAgfQoKICAgIH0gLy8gZW5kIGlmIG5vdCBpbiBjYWNoZQoKICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgLy8gRG8gc29tZSBzaXplIENoZWNrcyBpZiB0aGlzIGlzIGEgcHV0CiAgICAvL2lmICghaXNHZXQpCiAgICAvL3sKICAgICAgaWYgKFQxLnNpemUoKSArIEIxLnNpemUoKSA+PSBjKQogICAgICB7CiAgICAgICAgLyogQjEgKyBUMSBmdWxsPyAqLwogICAgICAgIGlmIChUMS5zaXplKCkgPCBjKQogICAgICAgIHsKICAgICAgICAgIC8qIFN0aWxsIHJvb20gaW4gVDE/ICovCiAgICAgICAgICB0ZW1wID0gKEVsZW1lbnREZXNjcmlwdG9yKSBCMS5yZW1vdmVMYXN0KCk7CiAgICAgICAgICBpZiAoIHRlbXAgIT0gbnVsbCApIHsKICAgICAgICAgICAgbWFwLnJlbW92ZSh0ZW1wLmtleSk7CiAgICAgICAgICB9CiAgICAgICAgICAvKiB5ZXM6IHRha2UgcGFnZSBvZmYgQjEgKi8KICAgICAgICAgIC8vdGVtcC0+cG9pbnRlciA9IHJlcGxhY2UoKTsgLyogZmluZCBuZXcgcGxhY2UgdG8gcHV0IHBhZ2UgKi8KICAgICAgICAgIHJlcGxhY2UodGVtcCk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAvKiBubzogQjEgbXVzdCBiZSBlbXB0eSAqLwogICAgICAgICAgLy90ZW1wID0gKEVsZW1lbnREZXNjcmlwdG9yKSBUMS5yZW1vdmVMYXN0KCk7IC8qIHRha2UgcGFnZSBvZmYgVDEgKi8KICAgICAgICAgIC8vbWFwLnJlbW92ZSh0ZW1wLmNlLmdldEtleSgpKTsKICAgICAgICAgIC8vaWYgKHRlbXAtPmRpcnR5KSBkZXN0YWdlKHRlbXApOyAvKiBpZiBkaXJ0eSwgZXZpY3QgYmVmb3JlIG92ZXJ3cml0ZSAqLwogICAgICAgICAgcmVwbGFjZSh0ZW1wKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgLyogQjEgKyBUMSBoYXZlIGxlc3MgdGhhbiBjIHBhZ2VzICovCiAgICAgICAgaWYgKFQxLnNpemUoKSArIFQyLnNpemUoKSArIEIxLnNpemUoKSArIEIyLnNpemUoKSA+PSBjKQogICAgICAgIHsKICAgICAgICAgIC8qIGNhY2hlIGZ1bGw/ICovCiAgICAgICAgICAvKiBZZXMsIGNhY2hlIGZ1bGw6ICovCiAgICAgICAgICBpZiAoVDEuc2l6ZSgpICsgVDIuc2l6ZSgpICsgQjEuc2l6ZSgpICsgQjIuc2l6ZSgpID49IDIgKiBjKQogICAgICAgICAgewogICAgICAgICAgICAvKiBjYWNoZSBpcyBmdWxsOiAqLwogICAgICAgICAgICAvKiB4IGZpbmQgYW5kIHJldXNlIEIyknMgTFJVICovCiAgICAgICAgICAgIHRlbXAgPSAoRWxlbWVudERlc2NyaXB0b3IpIEIyLnJlbW92ZUxhc3QoKTsKICAgICAgICAgICAgaWYgKCB0ZW1wICE9IG51bGwgKSB7CiAgICAgICAgICAgICAgbWFwLnJlbW92ZSh0ZW1wLmtleSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGVsc2UKICAgICAgICAgIHsKICAgICAgICAgICAgLyogY2FjaGUgZGlyZWN0b3J5IG5vdCBmdWxsLCBlYXN5IGNhc2UgKi8KICAgICAgICAgICAgOyAvL25vcAogICAgICAgICAgfQogICAgICAgICAgcmVwbGFjZSh0ZW1wKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIC8qIGNhY2hlIG5vdCBmdWxsLCBlYXN5IGNhc2UgKi8KICAgICAgICAgIDsgLy9ub3AKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmICghaXNHZXQgJiYgIWlzSGl0KQogICAgICB7CiAgICAgICAgdGVtcCA9IG5ldyBFbGVtZW50RGVzY3JpcHRvcihjZSk7CiAgICAgICAgdGVtcC5jZSA9IGNlOwogICAgICAgIHRlbXAubGlzdE51bSA9IF9UMV87CiAgICAgICAgVDEuYWRkRmlyc3QodGVtcCk7IC8qIHNlZW4gb25jZSByZWNlbnRseSwgcHV0IG9uIFQxICovCiAgICAgICAgdGhpcy5tYXAucHV0KHRlbXAuY2UuZ2V0S2V5KCksIHRlbXApOwogICAgICB9IC8vIGVuZCBpZiBwdXQKCgogICAgaWYgKHRlbXAgPT0gbnVsbCkKICAgIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gdGVtcC5jZTsKICB9CgogIC8qKgogICAqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc28gbXVjaCByZXBsYWNlIGFzIHJlbW92ZS4gIEl0IHB1c2hlcyB0aGUgbGVhc3QKICAgKiByZWNlbnRseSB1c2VkIGluIHQxIG9yIHQyIHRvIGEgZHVtbXkgaG9sZGVyLiBUaGUgaG9sZGVyIGtlZXBzIGEgZHVtbXkgb2JqZWN0CiAgICogdGhhdCBzdG9yZXMgdGhlIGtleSBzbyB0aGF0IHN1YnNlcXVlbnQgZ2V0cyBhbmQgcHV0cyBjYW4gaGVscCB0cmFpbiB0aGUKICAgKiBjYWNoZS4gIEl0ZW1zIGFyZSBzcG9vbGVkIGlmIHRoZXJlIGlzIGEgZGlzayBjYWNoZSBhdCB0aGlzIHBvaW50LgogICAqCiAgICogQHBhcmFtIG9yaWcgRWxlbWVudERlc2NyaXB0b3IKICAgKi8KICBwdWJsaWMgdm9pZCByZXBsYWNlKEVsZW1lbnREZXNjcmlwdG9yIG9yaWcpCiAgewogICAgdHJ5CiAgICB7CiAgICAgIEVsZW1lbnREZXNjcmlwdG9yIHRlbXA7CiAgICAgIGlmIChUMS5zaXplKCkgPj0gTWF0aC5tYXgoMSwgdGFyZ2V0X1QxKSkKICAgICAgeyAvLyBUMZJzIHNpemUgZXhjZWVkcyB0YXJnZXQ/CiAgICAgICAgLy8geWVzOiBUMSBpcyB0b28gYmlnCiAgICAgICAgdGVtcCA9IChFbGVtZW50RGVzY3JpcHRvcikgVDEuZ2V0TGFzdCgpOwogICAgICAgIGlmIChvcmlnID09IG51bGwgfHwgIW9yaWcua2V5LmVxdWFscyh0ZW1wLmtleSkpCiAgICAgICAgewogICAgICAgICAgaWYgKGxvZy5pc0RlYnVnRW5hYmxlZCgpKQogICAgICAgICAgewogICAgICAgICAgICBsb2cuZGVidWcoInJlcGxhY2UgLS0gVDEgdG8gQjEiKTsKICAgICAgICAgICAgbG9nLmRlYnVnKGdldFN0YXRzKCkpOwogICAgICAgICAgfQogICAgICAgICAgdGVtcCA9IChFbGVtZW50RGVzY3JpcHRvcikgVDEucmVtb3ZlTGFzdCgpOyAvLyBncmFiIExSVSBmcm9tIFQxCiAgICAgICAgICAvLyBudWxsaWZ5IG9iamVjdCwgdGVtcCBpcyBub3cganVzdCBhIGR1bW15IGNvbnRhaW5lciB0byBoZWxwCiAgICAgICAgICAvLyBhZGp1c3QgdGhlIGxydSBzaXplCiAgICAgICAgICB0cnkKICAgICAgICAgIHsKICAgICAgICAgICAgdGhpcy53YXRlcmZhbCh0ZW1wLmNlKTsKICAgICAgICAgIH0KICAgICAgICAgIGNhdGNoIChFeGNlcHRpb24gZSkKICAgICAgICAgIHsKICAgICAgICAgICAgbG9nLmVycm9yKGUpOwogICAgICAgICAgfQogICAgICAgICAgdGVtcC5jZSA9IG51bGw7CiAgICAgICAgICB0ZW1wLmxpc3ROdW0gPSBfQjFfOyAvLyBub3RlIHRoYXQgZmFjdAogICAgICAgICAgQjEuYWRkRmlyc3QodGVtcCk7IC8vIHB1dCBpdCBvbiBCMQogICAgICAgICAgLy9UMUxlbmd0aJc7IEIxTGVuZ3RoKys7IC8vIGJvb2trZWVwCiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICBpZiAobG9nLmlzRGVidWdFbmFibGVkKCkpCiAgICAgICAgICB7CiAgICAgICAgICAgIGxvZy5kZWJ1Zygib3JpZyA9PSB0ZW1wLCB0MSIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBlbHNlCiAgICAgIC8vIGlmIHQyIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB3aGF0IGlzIGxlZnQgaW4gYyBhZnRlciB0aGUgdGFyZ2V0CiAgICAgIGlmICggKCBUMi5zaXplKCkgKyBUMS5zaXplKCkgKSA+IGMgKQogICAgICB7CgogICAgICAgIC8vIG5vOiBUMSBpcyBub3QgdG9vIGJpZwogICAgICAgIHRlbXAgPSAoRWxlbWVudERlc2NyaXB0b3IpIFQyLmdldExhc3QoKTsKICAgICAgICBpZiAob3JpZyA9PSBudWxsIHx8ICFvcmlnLmtleS5lcXVhbHModGVtcC5rZXkpKQogICAgICAgIHsKICAgICAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgbG9nLmRlYnVnKCJyZXBsYWNlIC0tIFQyIHRvIEIyIik7CiAgICAgICAgICAgIGxvZy5kZWJ1ZyhnZXRTdGF0cygpKTsKICAgICAgICAgIH0KCiAgICAgICAgICB0ZW1wID0gKEVsZW1lbnREZXNjcmlwdG9yKSBUMi5yZW1vdmVMYXN0KCk7IC8vIGdyYWIgTFJVIHBhZ2Ugb2YgVDIKICAgICAgICAgIC8vIG51bGxpZnkgb2JqZWN0LCB0ZW1wIGlzIG5vdyBqdXN0IGEgZHVtbXkgY29udGFpbmVyIHRvIGhlbHAKICAgICAgICAgIC8vIGFkanVzdCB0aGUgbHJ1IHNpemUKICAgICAgICAgIHRyeQogICAgICAgICAgewogICAgICAgICAgICB0aGlzLndhdGVyZmFsKHRlbXAuY2UpOwogICAgICAgICAgfQogICAgICAgICAgY2F0Y2ggKEV4Y2VwdGlvbiBlKQogICAgICAgICAgewogICAgICAgICAgICBsb2cuZXJyb3IoZSk7CiAgICAgICAgICB9CiAgICAgICAgICB0ZW1wLmNlID0gbnVsbDsKICAgICAgICAgIHRlbXAubGlzdE51bSA9IF9CMl87IC8vIG5vdGUgdGhhdCBmYWN0CiAgICAgICAgICBCMi5hZGRGaXJzdCh0ZW1wKTsgLy8gcHV0IGl0IG9uIEIyCiAgICAgICAgICAvL1QyTGVuZ3RolzsgQjJMZW5ndGgrKzsgLy8gYm9va2tlZXAKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIGlmIChsb2cuaXNEZWJ1Z0VuYWJsZWQoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgbG9nLmRlYnVnKCJvcmlnID09IHRlbXAsIHQyIik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjYXRjaCAoRXhjZXB0aW9uIGUpCiAgICB7CiAgICAgIGxvZy5lcnJvcihlKTsKICAgIH0KICB9CgogIC8qKgogICAqIHJlbW92ZQogICAqCiAgICogQHBhcmFtIGtleSBTZXJpYWxpemFibGUKICAgKiBAcmV0dXJuIGJvb2xlYW4KICAgKi8KICBwdWJsaWMgYm9vbGVhbiByZW1vdmUoU2VyaWFsaXphYmxlIGtleSkKICB7CiAgICBFbGVtZW50RGVzY3JpcHRvciB0ZW1wID0gKEVsZW1lbnREZXNjcmlwdG9yKSBtYXAucmVtb3ZlKGtleSk7CiAgICBpZiAoIHRlbXAgIT0gbnVsbCApIHsKICAgICAgaW50IGxvYyA9IHRlbXAubGlzdE51bTsKICAgICAgaWYgKGxvYyA9PSBfVDFfKQogICAgICB7CiAgICAgICAgVDEucmVtb3ZlKHRlbXApOwogICAgICB9CiAgICAgIGVsc2UKICAgICAgaWYgKGxvYyA9PSBfVDJfKQogICAgICB7CiAgICAgICAgVDIucmVtb3ZlKHRlbXApOwogICAgICB9CiAgICAgIGVsc2UKICAgICAgaWYgKGxvYyA9PSBfQjFfKQogICAgICB7CiAgICAgICAgQjEucmVtb3ZlKHRlbXApOwogICAgICB9CiAgICAgIGVsc2UKICAgICAgaWYgKGxvYyA9PSBfQjJfKQogICAgICB7CiAgICAgICAgQjIucmVtb3ZlKHRlbXApOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIC8qKgogICAqIFJlbW92ZSBhbGwgb2YgdGhlIGVsZW1lbnRzIGZyb20gYm90aCB0aGUgTWFwIGFuZCB0aGUgbGlua2VkCiAgICogbGlzdCBpbXBsZW1lbnRhdGlvbi4gT3ZlcnJpZGVzIGJhc2UgY2xhc3MuCiAgICovCiAgcHVibGljIHN5bmNocm9uaXplZCB2b2lkIHJlbW92ZUFsbCgpIHRocm93cyBJT0V4Y2VwdGlvbgogIHsKICAgIG1hcC5jbGVhcigpOwogICAgVDEucmVtb3ZlQWxsKCk7CiAgICBUMi5yZW1vdmVBbGwoKTsKICAgIEIxLnJlbW92ZUFsbCgpOwogICAgQjIucmVtb3ZlQWxsKCk7CiAgfQoKICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgcHVibGljIFN0cmluZyBnZXRTdGF0cygpCiAgewogICAgcmV0dXJuIGdldFN0YXRpc3RpY3MoKS50b1N0cmluZygpOwogIH0KCiAgCiAgLyoKICAgKiAgKG5vbi1KYXZhZG9jKQogICAqIEBzZWUgb3JnLmFwYWNoZS5qY3MuZW5naW5lLm1lbW9yeS5NZW1vcnlDYWNoZSNnZXRTdGF0aXN0aWNzKCkKICAgKi8KICBwdWJsaWMgSVN0YXRzIGdldFN0YXRpc3RpY3MoKQogIHsKICAJSVN0YXRzIHN0YXRzID0gbmV3IFN0YXRzKCk7CiAgCXN0YXRzLnNldFR5cGVOYW1lKCAiTFJVIE1lbW9yeSBDYWNoZSIgKTsKICAJCiAgCUFycmF5TGlzdCBlbGVtcyA9IG5ldyBBcnJheUxpc3QoKTsKICAJCiAgCUlTdGF0RWxlbWVudCBzZSA9IG51bGw7CiAgCQogIAlzZSA9IG5ldyBTdGF0RWxlbWVudCgpOwogIAlzZS5zZXROYW1lKCAiVDEgU2l6ZSIgKTsKICAJc2Uuc2V0RGF0YSgiIiArIFQxLnNpemUoKSk7CgllbGVtcy5hZGQoc2UpOwoKICAJc2UgPSBuZXcgU3RhdEVsZW1lbnQoKTsKICAJc2Uuc2V0TmFtZSggIlQyIFNpemUiICk7CiAgCXNlLnNldERhdGEoIiIgKyBUMi5zaXplKCkpOwoJZWxlbXMuYWRkKHNlKTsKCQogIAlzZSA9IG5ldyBTdGF0RWxlbWVudCgpOwogIAlzZS5zZXROYW1lKCAiQjEgU2l6ZSIgKTsKICAJc2Uuc2V0RGF0YSgiIiArIEIxLnNpemUoKSk7CgllbGVtcy5hZGQoc2UpOwoKICAJc2UgPSBuZXcgU3RhdEVsZW1lbnQoKTsKICAJc2Uuc2V0TmFtZSggIkIyIFNpemUiICk7CiAgCXNlLnNldERhdGEoIiIgKyBCMi5zaXplKCkpOwoJZWxlbXMuYWRkKHNlKTsKCiAgCXNlID0gbmV3IFN0YXRFbGVtZW50KCk7CiAgCXNlLnNldE5hbWUoICJUYXJnZXQgVDEgU2l6ZSIgKTsKICAJc2Uuc2V0RGF0YSgiIiArIHRhcmdldF9UMSk7CgllbGVtcy5hZGQoc2UpOwoKCXNlID0gbmV3IFN0YXRFbGVtZW50KCk7CiAgCXNlLnNldE5hbWUoICJNYXAgU2l6ZSIgKTsKICAJc2Uuc2V0RGF0YSgiIiArIG1hcC5zaXplKCkpOwoJZWxlbXMuYWRkKHNlKTsKICAJCiAgCXNlID0gbmV3IFN0YXRFbGVtZW50KCk7CiAgCXNlLnNldE5hbWUoICJQdXQgQ291bnQiICk7CglzZS5zZXREYXRhKCIiICsgcHV0Q250KTsgIAkKCWVsZW1zLmFkZChzZSk7CiAgCQoJc2UgPSBuZXcgU3RhdEVsZW1lbnQoKTsKICAJc2Uuc2V0TmFtZSggIkhpdCBDb3VudCIgKTsKCXNlLnNldERhdGEoIiIgKyBoaXRDbnQpOwoJZWxlbXMuYWRkKHNlKTsKCiAgCXNlID0gbmV3IFN0YXRFbGVtZW50KCk7CiAgCXNlLnNldE5hbWUoICJNaXNzIENvdW50IiApOwogIAlzZS5zZXREYXRhKCIiICsgbWlzc0NudCk7CgllbGVtcy5hZGQoc2UpOwoJCgkvLyBnZXQgYW4gYXJyYXkgYW5kIHB1dCB0aGVtIGluIHRoZSBTdGF0cyBvYmplY3QKCUlTdGF0RWxlbWVudFtdIHNlcyA9IChJU3RhdEVsZW1lbnRbXSllbGVtcy50b0FycmF5KCBuZXcgU3RhdEVsZW1lbnRbMF0gKTsKCXN0YXRzLnNldFN0YXRFbGVtZW50cyggc2VzICk7CgoJLy8gaW50IHJhdGUgPSAoKGhpdENudCArIG1pc3NDbnQpICogMTAwKSAvIChoaXRDbnQgKiAxMDApICogMTAwOwogICAgLy9idWYuYXBwZW5kKCJcbiBIaXQgUmF0ZSA9ICIgKyByYXRlICsgIiAlIiApOwoJCiAgCXJldHVybiBzdGF0czsKICB9ICAgCiAgCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICBwdWJsaWMgY2xhc3MgRWxlbWVudERlc2NyaXB0b3IKICAgICAgZXh0ZW5kcyBNZW1vcnlFbGVtZW50RGVzY3JpcHRvcgogIHsKICAgIHB1YmxpYyBpbnQgbGlzdE51bTsKCiAgICBwdWJsaWMgU2VyaWFsaXphYmxlIGtleTsKCiAgICBwdWJsaWMgRWxlbWVudERlc2NyaXB0b3IoSUNhY2hlRWxlbWVudCBjZSkKICAgIHsKICAgICAgc3VwZXIoY2UpOwogICAgICBrZXkgPSBjZS5nZXRLZXkoKTsKICAgIH0KCiAgfQoKfQo=