LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUuY29tbW9ucy5pbWFnaW5nLmZvcm1hdHMucG5nOwoKaW1wb3J0IGphdmEuYXd0LmltYWdlLkJ1ZmZlcmVkSW1hZ2U7CmltcG9ydCBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLk91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEudXRpbC5IYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTWFwOwppbXBvcnQgamF2YS51dGlsLnppcC5EZWZsYXRlck91dHB1dFN0cmVhbTsKCmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMuaW1hZ2luZy5JbWFnZVdyaXRlRXhjZXB0aW9uOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmltYWdpbmcuUGl4ZWxEZW5zaXR5OwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmltYWdpbmcuY29tbW9uLlpMaWJVdGlsczsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy5pbWFnaW5nLnBhbGV0dGUuTWVkaWFuQ3V0UXVhbnRpemVyOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmltYWdpbmcucGFsZXR0ZS5QYWxldHRlOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmltYWdpbmcucGFsZXR0ZS5QYWxldHRlRmFjdG9yeTsKaW1wb3J0IG9yZy5hcGFjaGUuY29tbW9ucy5pbWFnaW5nLnV0aWwuRGVidWc7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMuaW1hZ2luZy51dGlsLlBhcmFtTWFwOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmltYWdpbmcudXRpbC5Vbmljb2RlVXRpbHM7CgpwdWJsaWMgY2xhc3MgUG5nV3JpdGVyIGltcGxlbWVudHMgUG5nQ29uc3RhbnRzCnsKICAgIHByaXZhdGUgZmluYWwgYm9vbGVhbiB2ZXJib3NlOwoKICAgIHB1YmxpYyBQbmdXcml0ZXIoYm9vbGVhbiB2ZXJib3NlKQogICAgewogICAgICAgIHRoaXMudmVyYm9zZSA9IHZlcmJvc2U7CiAgICB9CgogICAgcHVibGljIFBuZ1dyaXRlcihNYXAgcGFyYW1zKQogICAgewogICAgICAgIHRoaXMudmVyYm9zZSA9IFBhcmFtTWFwLmdldFBhcmFtQm9vbGVhbihwYXJhbXMsIFBBUkFNX0tFWV9WRVJCT1NFLAogICAgICAgICAgICAgICAgZmFsc2UpOwogICAgfQoKICAgIC8qCiAgICAgKiAxLiBJSERSOiBpbWFnZSBoZWFkZXIsIHdoaWNoIGlzIHRoZSBmaXJzdCBjaHVuayBpbiBhIFBORyBkYXRhc3RyZWFtLiAyLgogICAgICogUExURTogcGFsZXR0ZSB0YWJsZSBhc3NvY2lhdGVkIHdpdGggaW5kZXhlZCBQTkcgaW1hZ2VzLiAzLiBJREFUOiBpbWFnZQogICAgICogZGF0YSBjaHVua3MuIDQuIElFTkQ6IGltYWdlIHRyYWlsZXIsIHdoaWNoIGlzIHRoZSBsYXN0IGNodW5rIGluIGEgUE5HCiAgICAgKiBkYXRhc3RyZWFtLgogICAgICoKICAgICAqIFRoZSByZW1haW5pbmcgMTQgY2h1bmsgdHlwZXMgYXJlIHRlcm1lZCBhbmNpbGxhcnkgY2h1bmsgdHlwZXMsIHdoaWNoCiAgICAgKiBlbmNvZGVycyBtYXkgZ2VuZXJhdGUgYW5kIGRlY29kZXJzIG1heSBpbnRlcnByZXQuCiAgICAgKgogICAgICogMS4gVHJhbnNwYXJlbmN5IGluZm9ybWF0aW9uOiB0Uk5TIChzZWUgMTEuMy4yOiBUcmFuc3BhcmVuY3kgaW5mb3JtYXRpb24pLgogICAgICogMi4gQ29sb3VyIHNwYWNlIGluZm9ybWF0aW9uOiBjSFJNLCBnQU1BLCBpQ0NQLCBzQklULCBzUkdCIChzZWUgMTEuMy4zOgogICAgICogQ29sb3VyIHNwYWNlIGluZm9ybWF0aW9uKS4gMy4gVGV4dHVhbCBpbmZvcm1hdGlvbjogaVRYdCwgdEVYdCwgelRYdCAoc2VlCiAgICAgKiAxMS4zLjQ6IFRleHR1YWwgaW5mb3JtYXRpb24pLiA0LiBNaXNjZWxsYW5lb3VzIGluZm9ybWF0aW9uOiBiS0dELCBoSVNULAogICAgICogcEhZcywgc1BMVCAoc2VlIDExLjMuNTogTWlzY2VsbGFuZW91cyBpbmZvcm1hdGlvbikuIDUuIFRpbWUgaW5mb3JtYXRpb246CiAgICAgKiB0SU1FIChzZWUgMTEuMy42OiBUaW1lIHN0YW1wIGluZm9ybWF0aW9uKS4KICAgICAqLwoKICAgIHByaXZhdGUgZmluYWwgdm9pZCB3cml0ZUludChPdXRwdXRTdHJlYW0gb3MsIGludCB2YWx1ZSkgdGhyb3dzIElPRXhjZXB0aW9uCiAgICB7CiAgICAgICAgb3Mud3JpdGUoMHhmZiAmICh2YWx1ZSA+PiAyNCkpOwogICAgICAgIG9zLndyaXRlKDB4ZmYgJiAodmFsdWUgPj4gMTYpKTsKICAgICAgICBvcy53cml0ZSgweGZmICYgKHZhbHVlID4+IDgpKTsKICAgICAgICBvcy53cml0ZSgweGZmICYgKHZhbHVlID4+IDApKTsKICAgIH0KCiAgICBwcml2YXRlIGZpbmFsIHZvaWQgd3JpdGVDaHVuayhPdXRwdXRTdHJlYW0gb3MsIGJ5dGUgY2h1bmtUeXBlW10sCiAgICAgICAgICAgIGJ5dGUgZGF0YVtdKSB0aHJvd3MgSU9FeGNlcHRpb24KICAgIHsKICAgICAgICBpbnQgZGF0YUxlbmd0aCA9IGRhdGEgPT0gbnVsbCA/IDAgOiBkYXRhLmxlbmd0aDsKICAgICAgICB3cml0ZUludChvcywgZGF0YUxlbmd0aCk7CiAgICAgICAgb3Mud3JpdGUoY2h1bmtUeXBlKTsKICAgICAgICBpZiAoZGF0YSAhPSBudWxsKQogICAgICAgICAgICBvcy53cml0ZShkYXRhKTsKCiAgICAgICAgLy8gRGVidWcuZGVidWcoIndyaXRlQ2h1bmsgY2h1bmtUeXBlIiwgY2h1bmtUeXBlKTsKICAgICAgICAvLyBEZWJ1Zy5kZWJ1Zygid3JpdGVDaHVuayBkYXRhIiwgZGF0YSk7CgogICAgICAgIHsKICAgICAgICAgICAgUG5nQ3JjIHBuZ19jcmMgPSBuZXcgUG5nQ3JjKCk7CgogICAgICAgICAgICBsb25nIGNyYzEgPSBwbmdfY3JjLnN0YXJ0X3BhcnRpYWxfY3JjKGNodW5rVHlwZSwgY2h1bmtUeXBlLmxlbmd0aCk7CiAgICAgICAgICAgIGxvbmcgY3JjMiA9IGRhdGEgPT0gbnVsbCA/IGNyYzEgOiBwbmdfY3JjLmNvbnRpbnVlX3BhcnRpYWxfY3JjKAogICAgICAgICAgICAgICAgICAgIGNyYzEsIGRhdGEsIGRhdGEubGVuZ3RoKTsKICAgICAgICAgICAgaW50IGNyYyA9IChpbnQpIHBuZ19jcmMuZmluaXNoX3BhcnRpYWxfY3JjKGNyYzIpOwoKICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoImNyYzEiLCBjcmMxICsgIiAoIiArIExvbmcudG9IZXhTdHJpbmcoY3JjMSkKICAgICAgICAgICAgLy8gKyAiKSIpOwogICAgICAgICAgICAvLyBEZWJ1Zy5kZWJ1ZygiY3JjMiIsIGNyYzIgKyAiICgiICsgTG9uZy50b0hleFN0cmluZyhjcmMyKQogICAgICAgICAgICAvLyArICIpIik7CiAgICAgICAgICAgIC8vIERlYnVnLmRlYnVnKCJjcmMzIiwgY3JjICsgIiAoIiArIEludGVnZXIudG9IZXhTdHJpbmcoY3JjKQogICAgICAgICAgICAvLyArICIpIik7CgogICAgICAgICAgICB3cml0ZUludChvcywgY3JjKTsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgY2xhc3MgSW1hZ2VIZWFkZXIKICAgIHsKICAgICAgICBwdWJsaWMgZmluYWwgaW50IHdpZHRoOwogICAgICAgIHB1YmxpYyBmaW5hbCBpbnQgaGVpZ2h0OwogICAgICAgIHB1YmxpYyBmaW5hbCBieXRlIGJpdF9kZXB0aDsKICAgICAgICBwdWJsaWMgZmluYWwgYnl0ZSBjb2xvclR5cGU7CiAgICAgICAgcHVibGljIGZpbmFsIGJ5dGUgY29tcHJlc3Npb25NZXRob2Q7CiAgICAgICAgcHVibGljIGZpbmFsIGJ5dGUgZmlsdGVyTWV0aG9kOwogICAgICAgIHB1YmxpYyBmaW5hbCBieXRlIGludGVybGFjZU1ldGhvZDsKCiAgICAgICAgcHVibGljIEltYWdlSGVhZGVyKGludCB3aWR0aCwgaW50IGhlaWdodCwgYnl0ZSBiaXRfZGVwdGgsCiAgICAgICAgICAgICAgICBieXRlIGNvbG9yVHlwZSwgYnl0ZSBjb21wcmVzc2lvbk1ldGhvZCwgYnl0ZSBmaWx0ZXJNZXRob2QsCiAgICAgICAgICAgICAgICBieXRlIGludGVybGFjZU1ldGhvZCkKICAgICAgICB7CiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgIHRoaXMuYml0X2RlcHRoID0gYml0X2RlcHRoOwogICAgICAgICAgICB0aGlzLmNvbG9yVHlwZSA9IGNvbG9yVHlwZTsKICAgICAgICAgICAgdGhpcy5jb21wcmVzc2lvbk1ldGhvZCA9IGNvbXByZXNzaW9uTWV0aG9kOwogICAgICAgICAgICB0aGlzLmZpbHRlck1ldGhvZCA9IGZpbHRlck1ldGhvZDsKICAgICAgICAgICAgdGhpcy5pbnRlcmxhY2VNZXRob2QgPSBpbnRlcmxhY2VNZXRob2Q7CiAgICAgICAgfQoKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgd3JpdGVDaHVua0lIRFIoT3V0cHV0U3RyZWFtIG9zLCBJbWFnZUhlYWRlciB2YWx1ZSkKICAgICAgICAgICAgdGhyb3dzIElPRXhjZXB0aW9uCiAgICB7CiAgICAgICAgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGJhb3MgPSBuZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CiAgICAgICAgd3JpdGVJbnQoYmFvcywgdmFsdWUud2lkdGgpOwogICAgICAgIHdyaXRlSW50KGJhb3MsIHZhbHVlLmhlaWdodCk7CiAgICAgICAgYmFvcy53cml0ZSgweGZmICYgdmFsdWUuYml0X2RlcHRoKTsKICAgICAgICBiYW9zLndyaXRlKDB4ZmYgJiB2YWx1ZS5jb2xvclR5cGUpOwogICAgICAgIGJhb3Mud3JpdGUoMHhmZiAmIHZhbHVlLmNvbXByZXNzaW9uTWV0aG9kKTsKICAgICAgICBiYW9zLndyaXRlKDB4ZmYgJiB2YWx1ZS5maWx0ZXJNZXRob2QpOwogICAgICAgIGJhb3Mud3JpdGUoMHhmZiAmIHZhbHVlLmludGVybGFjZU1ldGhvZCk7CgogICAgICAgIC8vIERlYnVnLmRlYnVnKCJiYW9zIiwgYmFvcy50b0J5dGVBcnJheSgpKTsKCiAgICAgICAgd3JpdGVDaHVuayhvcywgSUhEUl9DSFVOS19UWVBFLnRvQnl0ZUFycmF5KCksIGJhb3MudG9CeXRlQXJyYXkoKSk7CiAgICB9CgogICAgcHJpdmF0ZSB2b2lkIHdyaXRlQ2h1bmtpVFh0KE91dHB1dFN0cmVhbSBvcywgUG5nVGV4dC5pVFh0IHRleHQpCiAgICAgICAgICAgIHRocm93cyBJT0V4Y2VwdGlvbiwgSW1hZ2VXcml0ZUV4Y2VwdGlvbgogICAgewogICAgICAgIGlmICghVW5pY29kZVV0aWxzLmlzVmFsaWRJU09fODg1OV8xKHRleHQua2V5d29yZCkpCiAgICAgICAgICAgIHRocm93IG5ldyBJbWFnZVdyaXRlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJQbmcgdEVYdCBjaHVuayBrZXl3b3JkIGlzIG5vdCBJU08tODg1OS0xOiAiICsgdGV4dC5rZXl3b3JkKTsKICAgICAgICBpZiAoIVVuaWNvZGVVdGlscy5pc1ZhbGlkSVNPXzg4NTlfMSh0ZXh0Lmxhbmd1YWdlVGFnKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEltYWdlV3JpdGVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIlBuZyB0RVh0IGNodW5rIGxhbmd1YWdlIHRhZyBpcyBub3QgSVNPLTg4NTktMTogIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgKyB0ZXh0Lmxhbmd1YWdlVGFnKTsKCiAgICAgICAgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGJhb3MgPSBuZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CgogICAgICAgIC8vIGtleXdvcmQKICAgICAgICBiYW9zLndyaXRlKHRleHQua2V5d29yZC5nZXRCeXRlcygiSVNPLTg4NTktMSIpKTsKICAgICAgICBiYW9zLndyaXRlKDApOwoKICAgICAgICBiYW9zLndyaXRlKDEpOyAvLyBjb21wcmVzc2VkIGZsYWcsIHRydWUKICAgICAgICBiYW9zLndyaXRlKENPTVBSRVNTSU9OX0RFRkxBVEVfSU5GTEFURSk7IC8vIGNvbXByZXNzaW9uIG1ldGhvZAoKICAgICAgICAvLyBsYW5ndWFnZSB0YWcKICAgICAgICBiYW9zLndyaXRlKHRleHQubGFuZ3VhZ2VUYWcuZ2V0Qnl0ZXMoIklTTy04ODU5LTEiKSk7CiAgICAgICAgYmFvcy53cml0ZSgwKTsKCiAgICAgICAgLy8gdHJhbnNsYXRlZCBrZXl3b3JkCiAgICAgICAgYmFvcy53cml0ZSh0ZXh0LnRyYW5zbGF0ZWRLZXl3b3JkLmdldEJ5dGVzKCJ1dGYtOCIpKTsKICAgICAgICBiYW9zLndyaXRlKDApOwoKICAgICAgICBiYW9zLndyaXRlKG5ldyBaTGliVXRpbHMoKS5kZWZsYXRlKHRleHQudGV4dC5nZXRCeXRlcygidXRmLTgiKSkpOwoKICAgICAgICB3cml0ZUNodW5rKG9zLCBpVFh0X0NIVU5LX1RZUEUudG9CeXRlQXJyYXkoKSwgYmFvcy50b0J5dGVBcnJheSgpKTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgd3JpdGVDaHVua3pUWHQoT3V0cHV0U3RyZWFtIG9zLCBQbmdUZXh0LnpUWHQgdGV4dCkKICAgICAgICAgICAgdGhyb3dzIElPRXhjZXB0aW9uLCBJbWFnZVdyaXRlRXhjZXB0aW9uCiAgICB7CiAgICAgICAgaWYgKCFVbmljb2RlVXRpbHMuaXNWYWxpZElTT184ODU5XzEodGV4dC5rZXl3b3JkKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEltYWdlV3JpdGVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIlBuZyB6VFh0IGNodW5rIGtleXdvcmQgaXMgbm90IElTTy04ODU5LTE6ICIgKyB0ZXh0LmtleXdvcmQpOwogICAgICAgIGlmICghVW5pY29kZVV0aWxzLmlzVmFsaWRJU09fODg1OV8xKHRleHQudGV4dCkpCiAgICAgICAgICAgIHRocm93IG5ldyBJbWFnZVdyaXRlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJQbmcgelRYdCBjaHVuayB0ZXh0IGlzIG5vdCBJU08tODg1OS0xOiAiICsgdGV4dC50ZXh0KTsKCiAgICAgICAgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGJhb3MgPSBuZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CgogICAgICAgIC8vIGtleXdvcmQKICAgICAgICBiYW9zLndyaXRlKHRleHQua2V5d29yZC5nZXRCeXRlcygiSVNPLTg4NTktMSIpKTsKICAgICAgICBiYW9zLndyaXRlKDApOwoKICAgICAgICAvLyBjb21wcmVzc2lvbiBtZXRob2QKICAgICAgICBiYW9zLndyaXRlKFBuZ0NvbnN0YW50cy5DT01QUkVTU0lPTl9ERUZMQVRFX0lORkxBVEUpOwoKICAgICAgICAvLyB0ZXh0CiAgICAgICAgYmFvcwogICAgICAgICAgICAgICAgLndyaXRlKG5ldyBaTGliVXRpbHMoKS5kZWZsYXRlKHRleHQudGV4dAogICAgICAgICAgICAgICAgICAgICAgICAuZ2V0Qnl0ZXMoIklTTy04ODU5LTEiKSkpOwoKICAgICAgICB3cml0ZUNodW5rKG9zLCB6VFh0X0NIVU5LX1RZUEUudG9CeXRlQXJyYXkoKSwgYmFvcy50b0J5dGVBcnJheSgpKTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgd3JpdGVDaHVua3RFWHQoT3V0cHV0U3RyZWFtIG9zLCBQbmdUZXh0LnRFWHQgdGV4dCkKICAgICAgICAgICAgdGhyb3dzIElPRXhjZXB0aW9uLCBJbWFnZVdyaXRlRXhjZXB0aW9uCiAgICB7CiAgICAgICAgaWYgKCFVbmljb2RlVXRpbHMuaXNWYWxpZElTT184ODU5XzEodGV4dC5rZXl3b3JkKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEltYWdlV3JpdGVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIlBuZyB0RVh0IGNodW5rIGtleXdvcmQgaXMgbm90IElTTy04ODU5LTE6ICIgKyB0ZXh0LmtleXdvcmQpOwogICAgICAgIGlmICghVW5pY29kZVV0aWxzLmlzVmFsaWRJU09fODg1OV8xKHRleHQudGV4dCkpCiAgICAgICAgICAgIHRocm93IG5ldyBJbWFnZVdyaXRlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJQbmcgdEVYdCBjaHVuayB0ZXh0IGlzIG5vdCBJU08tODg1OS0xOiAiICsgdGV4dC50ZXh0KTsKCiAgICAgICAgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGJhb3MgPSBuZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CgogICAgICAgIC8vIGtleXdvcmQKICAgICAgICBiYW9zLndyaXRlKHRleHQua2V5d29yZC5nZXRCeXRlcygiSVNPLTg4NTktMSIpKTsKICAgICAgICBiYW9zLndyaXRlKDApOwoKICAgICAgICAvLyB0ZXh0CiAgICAgICAgYmFvcy53cml0ZSh0ZXh0LnRleHQuZ2V0Qnl0ZXMoIklTTy04ODU5LTEiKSk7CgogICAgICAgIHdyaXRlQ2h1bmsob3MsIHRFWHRfQ0hVTktfVFlQRS50b0J5dGVBcnJheSgpLCBiYW9zLnRvQnl0ZUFycmF5KCkpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCB3cml0ZUNodW5rWG1waVRYdChPdXRwdXRTdHJlYW0gb3MsIFN0cmluZyB4bXBYbWwpCiAgICAgICAgICAgIHRocm93cyBJT0V4Y2VwdGlvbgogICAgewoKICAgICAgICBCeXRlQXJyYXlPdXRwdXRTdHJlYW0gYmFvcyA9IG5ldyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0oKTsKCiAgICAgICAgLy8ga2V5d29yZAogICAgICAgIGJhb3Mud3JpdGUoWE1QX0tFWVdPUkQuZ2V0Qnl0ZXMoIklTTy04ODU5LTEiKSk7CiAgICAgICAgYmFvcy53cml0ZSgwKTsKCiAgICAgICAgYmFvcy53cml0ZSgxKTsgLy8gY29tcHJlc3NlZCBmbGFnLCB0cnVlCiAgICAgICAgYmFvcy53cml0ZShDT01QUkVTU0lPTl9ERUZMQVRFX0lORkxBVEUpOyAvLyBjb21wcmVzc2lvbiBtZXRob2QKCiAgICAgICAgYmFvcy53cml0ZSgwKTsgLy8gbGFuZ3VhZ2UgdGFnIChpZ25vcmUpLiBUT0RPCgogICAgICAgIC8vIHRyYW5zbGF0ZWQga2V5d29yZAogICAgICAgIGJhb3Mud3JpdGUoWE1QX0tFWVdPUkQuZ2V0Qnl0ZXMoInV0Zi04IikpOwogICAgICAgIGJhb3Mud3JpdGUoMCk7CgogICAgICAgIGJhb3Mud3JpdGUobmV3IFpMaWJVdGlscygpLmRlZmxhdGUoeG1wWG1sLmdldEJ5dGVzKCJ1dGYtOCIpKSk7CgogICAgICAgIHdyaXRlQ2h1bmsob3MsIGlUWHRfQ0hVTktfVFlQRS50b0J5dGVBcnJheSgpLCBiYW9zLnRvQnl0ZUFycmF5KCkpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCB3cml0ZUNodW5rUExURShPdXRwdXRTdHJlYW0gb3MsIFBhbGV0dGUgcGFsZXR0ZSkKICAgICAgICAgICAgdGhyb3dzIElPRXhjZXB0aW9uCiAgICB7CiAgICAgICAgaW50IGxlbmd0aCA9IHBhbGV0dGUubGVuZ3RoKCk7CiAgICAgICAgYnl0ZSBieXRlc1tdID0gbmV3IGJ5dGVbbGVuZ3RoICogM107CgogICAgICAgIC8vIERlYnVnLmRlYnVnKCJsZW5ndGgiLCBsZW5ndGgpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBpbnQgcmdiID0gcGFsZXR0ZS5nZXRFbnRyeShpKTsKICAgICAgICAgICAgaW50IGluZGV4ID0gaSAqIDM7CiAgICAgICAgICAgIC8vIERlYnVnLmRlYnVnKCJpbmRleCIsIGluZGV4KTsKICAgICAgICAgICAgYnl0ZXNbaW5kZXggKyAwXSA9IChieXRlKSAoMHhmZiAmIChyZ2IgPj4gMTYpKTsKICAgICAgICAgICAgYnl0ZXNbaW5kZXggKyAxXSA9IChieXRlKSAoMHhmZiAmIChyZ2IgPj4gOCkpOwogICAgICAgICAgICBieXRlc1tpbmRleCArIDJdID0gKGJ5dGUpICgweGZmICYgKHJnYiA+PiAwKSk7CiAgICAgICAgfQoKICAgICAgICB3cml0ZUNodW5rKG9zLCBQTFRFX0NIVU5LX1RZUEUudG9CeXRlQXJyYXkoKSwgYnl0ZXMpOwogICAgfQoKICAgIHByaXZhdGUgdm9pZCB3cml0ZUNodW5rSUVORChPdXRwdXRTdHJlYW0gb3MpIHRocm93cyBJT0V4Y2VwdGlvbgogICAgewogICAgICAgIHdyaXRlQ2h1bmsob3MsIElFTkRfQ0hVTktfVFlQRS50b0J5dGVBcnJheSgpLCBudWxsKTsKICAgIH0KCiAgICBwcml2YXRlIHZvaWQgd3JpdGVDaHVua0lEQVQoT3V0cHV0U3RyZWFtIG9zLCBieXRlIGJ5dGVzW10pCiAgICAgICAgICAgIHRocm93cyBJT0V4Y2VwdGlvbgogICAgewogICAgICAgIHdyaXRlQ2h1bmsob3MsIElEQVRfQ0hVTktfVFlQRS50b0J5dGVBcnJheSgpLCBieXRlcyk7CiAgICB9CiAgICAKICAgIHByaXZhdGUgdm9pZCB3cml0ZUNodW5rUEhZUyhPdXRwdXRTdHJlYW0gb3MsIGludCB4UFBVLCBpbnQgeVBQVSwgYnl0ZSB1bml0cykKICAgICAgICAgICAgdGhyb3dzIElPRXhjZXB0aW9uCiAgICB7CiAgICAgICAgYnl0ZVtdIGJ5dGVzID0gbmV3IGJ5dGVbOV07CiAgICAgICAgYnl0ZXNbMF0gPSAoYnl0ZSkgKDB4ZmYgJiAoeFBQVSA+PiAyNCkpOwogICAgICAgIGJ5dGVzWzFdID0gKGJ5dGUpICgweGZmICYgKHhQUFUgPj4gMTYpKTsKICAgICAgICBieXRlc1syXSA9IChieXRlKSAoMHhmZiAmICh4UFBVID4+IDgpKTsKICAgICAgICBieXRlc1szXSA9IChieXRlKSAoMHhmZiAmICh4UFBVID4+IDApKTsKICAgICAgICBieXRlc1s0XSA9IChieXRlKSAoMHhmZiAmICh5UFBVID4+IDI0KSk7CiAgICAgICAgYnl0ZXNbNV0gPSAoYnl0ZSkgKDB4ZmYgJiAoeVBQVSA+PiAxNikpOwogICAgICAgIGJ5dGVzWzZdID0gKGJ5dGUpICgweGZmICYgKHlQUFUgPj4gOCkpOwogICAgICAgIGJ5dGVzWzddID0gKGJ5dGUpICgweGZmICYgKHlQUFUgPj4gMCkpOwogICAgICAgIGJ5dGVzWzhdID0gdW5pdHM7CiAgICAgICAgd3JpdGVDaHVuayhvcywgSVBIWVNfQ0hVTktfVFlQRS50b0J5dGVBcnJheSgpLCBieXRlcyk7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIGdldENvbG91clR5cGUoYm9vbGVhbiBoYXNBbHBoYSwgYm9vbGVhbiBpc0dyYXlzY2FsZSkKICAgIHsKICAgICAgICBieXRlIHJlc3VsdDsKCiAgICAgICAgYm9vbGVhbiBpbmRleCA9IGZhbHNlOyAvLyBjaGFybGVzCgogICAgICAgIGlmIChpbmRleCkKICAgICAgICAgICAgcmVzdWx0ID0gQ09MT1JfVFlQRV9JTkRFWEVEX0NPTE9SOwogICAgICAgIGVsc2UgaWYgKGlzR3JheXNjYWxlKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGhhc0FscGhhKQogICAgICAgICAgICAgICAgcmVzdWx0ID0gQ09MT1JfVFlQRV9HUkVZU0NBTEVfV0lUSF9BTFBIQTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcmVzdWx0ID0gQ09MT1JfVFlQRV9HUkVZU0NBTEU7CiAgICAgICAgfSBlbHNlIGlmIChoYXNBbHBoYSkKICAgICAgICAgICAgcmVzdWx0ID0gQ09MT1JfVFlQRV9UUlVFX0NPTE9SX1dJVEhfQUxQSEE7CiAgICAgICAgZWxzZQogICAgICAgICAgICByZXN1bHQgPSBDT0xPUl9UWVBFX1RSVUVfQ09MT1I7CgogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CgogICAgcHJpdmF0ZSBieXRlIGdldEJpdERlcHRoKGZpbmFsIGJ5dGUgY29sb3JUeXBlLCBNYXAgcGFyYW1zKQogICAgewogICAgICAgIGJ5dGUgcmVzdWx0ID0gODsKCiAgICAgICAgT2JqZWN0IG8gPSBwYXJhbXMuZ2V0KFBBUkFNX0tFWV9QTkdfQklUX0RFUFRIKTsKICAgICAgICBpZiAobyAhPSBudWxsICYmIG8gaW5zdGFuY2VvZiBOdW1iZXIpCiAgICAgICAgewogICAgICAgICAgICBpbnQgdmFsdWUgPSAoKE51bWJlcikgbykuaW50VmFsdWUoKTsKICAgICAgICAgICAgc3dpdGNoICh2YWx1ZSkKICAgICAgICAgICAgewogICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgICAgICByZXN1bHQgPSAoYnl0ZSkgdmFsdWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgfQogICAgICAgICAgICBzd2l0Y2ggKGNvbG9yVHlwZSkKICAgICAgICAgICAgewogICAgICAgICAgICBjYXNlIENPTE9SX1RZUEVfR1JFWVNDQUxFOgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgQ09MT1JfVFlQRV9JTkRFWEVEX0NPTE9SOgogICAgICAgICAgICAgICAgcmVzdWx0ID0gKGJ5dGUpIE1hdGgubWluKDgsIHJlc3VsdCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBDT0xPUl9UWVBFX0dSRVlTQ0FMRV9XSVRIX0FMUEhBOgogICAgICAgICAgICBjYXNlIENPTE9SX1RZUEVfVFJVRV9DT0xPUjoKICAgICAgICAgICAgY2FzZSBDT0xPUl9UWVBFX1RSVUVfQ09MT1JfV0lUSF9BTFBIQToKICAgICAgICAgICAgICAgIHJlc3VsdCA9IChieXRlKSBNYXRoLm1heCg4LCByZXN1bHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CgogICAgLyoKICAgICAqIGJldHdlZW4gdHdvIGNodW5rIHR5cGVzIGluZGljYXRlcyBhbHRlcm5hdGl2ZXMuIFRhYmxlIDUuMyCXIENodW5rCiAgICAgKiBvcmRlcmluZyBydWxlcyBDcml0aWNhbCBjaHVua3MgKHNoYWxsIGFwcGVhciBpbiB0aGlzIG9yZGVyLCBleGNlcHQgUExURQogICAgICogaXMgb3B0aW9uYWwpIENodW5rIG5hbWUgTXVsdGlwbGUgYWxsb3dlZCBPcmRlcmluZyBjb25zdHJhaW50cyBJSERSIE5vCiAgICAgKiBTaGFsbCBiZSBmaXJzdCBQTFRFIE5vIEJlZm9yZSBmaXJzdCBJREFUIElEQVQgWWVzIE11bHRpcGxlIElEQVQgY2h1bmtzCiAgICAgKiBzaGFsbCBiZSBjb25zZWN1dGl2ZSBJRU5EIE5vIFNoYWxsIGJlIGxhc3QgQW5jaWxsYXJ5IGNodW5rcyAobmVlZCBub3QKICAgICAqIGFwcGVhciBpbiB0aGlzIG9yZGVyKSBDaHVuayBuYW1lIE11bHRpcGxlIGFsbG93ZWQgT3JkZXJpbmcgY29uc3RyYWludHMKICAgICAqIGNIUk0gTm8gQmVmb3JlIFBMVEUgYW5kIElEQVQgZ0FNQSBObyBCZWZvcmUgUExURSBhbmQgSURBVCBpQ0NQIE5vIEJlZm9yZQogICAgICogUExURSBhbmQgSURBVC4gSWYgdGhlIGlDQ1AgY2h1bmsgaXMgcHJlc2VudCwgdGhlIHNSR0IgY2h1bmsgc2hvdWxkIG5vdCBiZQogICAgICogcHJlc2VudC4gc0JJVCBObyBCZWZvcmUgUExURSBhbmQgSURBVCBzUkdCIE5vIEJlZm9yZSBQTFRFIGFuZCBJREFULiBJZgogICAgICogdGhlIHNSR0IgY2h1bmsgaXMgcHJlc2VudCwgdGhlIGlDQ1AgY2h1bmsgc2hvdWxkIG5vdCBiZSBwcmVzZW50LiBiS0dEIE5vCiAgICAgKiBBZnRlciBQTFRFOyBiZWZvcmUgSURBVCBoSVNUIE5vIEFmdGVyIFBMVEU7IGJlZm9yZSBJREFUIHRSTlMgTm8gQWZ0ZXIKICAgICAqIFBMVEU7IGJlZm9yZSBJREFUIHBIWXMgTm8gQmVmb3JlIElEQVQgc1BMVCBZZXMgQmVmb3JlIElEQVQgdElNRSBObyBOb25lCiAgICAgKiBpVFh0IFllcyBOb25lIHRFWHQgWWVzIE5vbmUgelRYdCBZZXMgTm9uZQogICAgICovCgogICAgcHVibGljIHZvaWQgd3JpdGVJbWFnZShCdWZmZXJlZEltYWdlIHNyYywgT3V0cHV0U3RyZWFtIG9zLCBNYXAgcGFyYW1zKQogICAgICAgICAgICB0aHJvd3MgSW1hZ2VXcml0ZUV4Y2VwdGlvbiwgSU9FeGNlcHRpb24KICAgIHsKICAgICAgICAvLyBtYWtlIGNvcHkgb2YgcGFyYW1zOyB3ZSdsbCBjbGVhciBrZXlzIGFzIHdlIGNvbnN1bWUgdGhlbS4KICAgICAgICBwYXJhbXMgPSBuZXcgSGFzaE1hcChwYXJhbXMpOwoKICAgICAgICAvLyBjbGVhciBmb3JtYXQga2V5LgogICAgICAgIGlmIChwYXJhbXMuY29udGFpbnNLZXkoUEFSQU1fS0VZX0ZPUk1BVCkpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX0ZPUk1BVCk7CiAgICAgICAgLy8gY2xlYXIgdmVyYm9zZSBrZXkuCiAgICAgICAgaWYgKHBhcmFtcy5jb250YWluc0tleShQQVJBTV9LRVlfVkVSQk9TRSkpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX1ZFUkJPU0UpOwoKICAgICAgICBNYXAgcmF3UGFyYW1zID0gbmV3IEhhc2hNYXAocGFyYW1zKTsKICAgICAgICBpZiAocGFyYW1zLmNvbnRhaW5zS2V5KFBBUkFNX0tFWV9QTkdfRk9SQ0VfVFJVRV9DT0xPUikpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX1BOR19GT1JDRV9UUlVFX0NPTE9SKTsKICAgICAgICBpZiAocGFyYW1zLmNvbnRhaW5zS2V5KFBBUkFNX0tFWV9QTkdfRk9SQ0VfSU5ERVhFRF9DT0xPUikpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX1BOR19GT1JDRV9JTkRFWEVEX0NPTE9SKTsKICAgICAgICBpZiAocGFyYW1zLmNvbnRhaW5zS2V5KFBBUkFNX0tFWV9QTkdfQklUX0RFUFRIKSkKICAgICAgICAgICAgcGFyYW1zLnJlbW92ZShQQVJBTV9LRVlfUE5HX0JJVF9ERVBUSCk7CiAgICAgICAgaWYgKHBhcmFtcy5jb250YWluc0tleShQQVJBTV9LRVlfWE1QX1hNTCkpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX1hNUF9YTUwpOwogICAgICAgIGlmIChwYXJhbXMuY29udGFpbnNLZXkoUEFSQU1fS0VZX1BOR19URVhUX0NIVU5LUykpCiAgICAgICAgICAgIHBhcmFtcy5yZW1vdmUoUEFSQU1fS0VZX1BOR19URVhUX0NIVU5LUyk7CiAgICAgICAgcGFyYW1zLnJlbW92ZShQQVJBTV9LRVlfUElYRUxfREVOU0lUWSk7CiAgICAgICAgaWYgKHBhcmFtcy5zaXplKCkgPiAwKQogICAgICAgIHsKICAgICAgICAgICAgT2JqZWN0IGZpcnN0S2V5ID0gcGFyYW1zLmtleVNldCgpLml0ZXJhdG9yKCkubmV4dCgpOwogICAgICAgICAgICB0aHJvdyBuZXcgSW1hZ2VXcml0ZUV4Y2VwdGlvbigiVW5rbm93biBwYXJhbWV0ZXI6ICIgKyBmaXJzdEtleSk7CiAgICAgICAgfQogICAgICAgIHBhcmFtcyA9IHJhd1BhcmFtczsKCiAgICAgICAgaW50IHdpZHRoID0gc3JjLmdldFdpZHRoKCk7CiAgICAgICAgaW50IGhlaWdodCA9IHNyYy5nZXRIZWlnaHQoKTsKCiAgICAgICAgYm9vbGVhbiBoYXNBbHBoYSA9IG5ldyBQYWxldHRlRmFjdG9yeSgpLmhhc1RyYW5zcGFyZW5jeShzcmMpOwogICAgICAgIGlmICh2ZXJib3NlKQogICAgICAgICAgICBEZWJ1Zy5kZWJ1ZygiaGFzQWxwaGEiLCBoYXNBbHBoYSk7CiAgICAgICAgLy8gaW50IHRyYW5zcGFyZW5jeSA9IG5ldyBQYWxldHRlRmFjdG9yeSgpLmdldFRyYW5zcGFyZW5jeShzcmMpOwoKICAgICAgICBib29sZWFuIGlzR3JheXNjYWxlID0gbmV3IFBhbGV0dGVGYWN0b3J5KCkuaXNHcmF5c2NhbGUoc3JjKTsKICAgICAgICBpZiAodmVyYm9zZSkKICAgICAgICAgICAgRGVidWcuZGVidWcoImlzR3JheXNjYWxlIiwgaXNHcmF5c2NhbGUpOwoKICAgICAgICBieXRlIGNvbG9yVHlwZTsKICAgICAgICB7CiAgICAgICAgICAgIGJvb2xlYW4gZm9yY2VJbmRleGVkQ29sb3IgPSBQYXJhbU1hcC5nZXRQYXJhbUJvb2xlYW4ocGFyYW1zLAogICAgICAgICAgICAgICAgICAgIFBBUkFNX0tFWV9QTkdfRk9SQ0VfSU5ERVhFRF9DT0xPUiwgZmFsc2UpOwogICAgICAgICAgICBib29sZWFuIGZvcmNlVHJ1ZUNvbG9yID0gUGFyYW1NYXAuZ2V0UGFyYW1Cb29sZWFuKHBhcmFtcywKICAgICAgICAgICAgICAgICAgICBQQVJBTV9LRVlfUE5HX0ZPUkNFX1RSVUVfQ09MT1IsIGZhbHNlKTsKCiAgICAgICAgICAgIGlmIChmb3JjZUluZGV4ZWRDb2xvciAmJiBmb3JjZVRydWVDb2xvcikKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbWFnZVdyaXRlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICAgICAiUGFyYW1zOiBDYW5ub3QgZm9yY2UgYm90aCBpbmRleGVkIGFuZCB0cnVlIGNvbG9yIG1vZGVzIik7CiAgICAgICAgICAgIGVsc2UgaWYgKGZvcmNlSW5kZXhlZENvbG9yKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBjb2xvclR5cGUgPSBDT0xPUl9UWVBFX0lOREVYRURfQ09MT1I7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZm9yY2VUcnVlQ29sb3IpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNvbG9yVHlwZSA9IChieXRlKSAoaGFzQWxwaGEgPyBDT0xPUl9UWVBFX1RSVUVfQ09MT1JfV0lUSF9BTFBIQQogICAgICAgICAgICAgICAgICAgICAgICA6IENPTE9SX1RZUEVfVFJVRV9DT0xPUik7CiAgICAgICAgICAgICAgICBpc0dyYXlzY2FsZSA9IGZhbHNlOwogICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgIGNvbG9yVHlwZSA9IGdldENvbG91clR5cGUoaGFzQWxwaGEsIGlzR3JheXNjYWxlKTsKICAgICAgICAgICAgaWYgKHZlcmJvc2UpCiAgICAgICAgICAgICAgICBEZWJ1Zy5kZWJ1ZygiY29sb3JUeXBlIiwgY29sb3JUeXBlKTsKICAgICAgICB9CgogICAgICAgIGJ5dGUgYml0RGVwdGggPSBnZXRCaXREZXB0aChjb2xvclR5cGUsIHBhcmFtcyk7CiAgICAgICAgaWYgKHZlcmJvc2UpCiAgICAgICAgICAgIERlYnVnLmRlYnVnKCJiaXRfZGVwdGgiLCBiaXREZXB0aCk7CgogICAgICAgIGludCBzYW1wbGVEZXB0aDsKICAgICAgICBpZiAoY29sb3JUeXBlID09IENPTE9SX1RZUEVfSU5ERVhFRF9DT0xPUikKICAgICAgICAgICAgc2FtcGxlRGVwdGggPSA4OwogICAgICAgIGVsc2UKICAgICAgICAgICAgc2FtcGxlRGVwdGggPSBiaXREZXB0aDsKICAgICAgICBpZiAodmVyYm9zZSkKICAgICAgICAgICAgRGVidWcuZGVidWcoInNhbXBsZV9kZXB0aCIsIHNhbXBsZURlcHRoKTsKCiAgICAgICAgewogICAgICAgICAgICBQTkdfU2lnbmF0dXJlLndyaXRlVG8ob3MpOwogICAgICAgIH0KICAgICAgICB7CiAgICAgICAgICAgIC8vIElIRFIgbXVzdCBiZSBmaXJzdAoKICAgICAgICAgICAgYnl0ZSBjb21wcmVzc2lvbk1ldGhvZCA9IENPTVBSRVNTSU9OX1RZUEVfSU5GTEFURV9ERUZMQVRFOwogICAgICAgICAgICBieXRlIGZpbHRlck1ldGhvZCA9IEZJTFRFUl9NRVRIT0RfQURBUFRJVkU7CiAgICAgICAgICAgIGJ5dGUgaW50ZXJsYWNlTWV0aG9kID0gSU5URVJMQUNFX01FVEhPRF9OT05FOwoKICAgICAgICAgICAgSW1hZ2VIZWFkZXIgaW1hZ2VIZWFkZXIgPSBuZXcgSW1hZ2VIZWFkZXIod2lkdGgsIGhlaWdodCwgYml0RGVwdGgsCiAgICAgICAgICAgICAgICAgICAgY29sb3JUeXBlLCBjb21wcmVzc2lvbk1ldGhvZCwgZmlsdGVyTWV0aG9kLCBpbnRlcmxhY2VNZXRob2QpOwoKICAgICAgICAgICAgd3JpdGVDaHVua0lIRFIob3MsIGltYWdlSGVhZGVyKTsKICAgICAgICB9CgogICAgICAgIHsKICAgICAgICAgICAgLy8gc1JHQiBObyBCZWZvcmUgUExURSBhbmQgSURBVC4gSWYgdGhlIHNSR0IgY2h1bmsgaXMgcHJlc2VudCwgdGhlCiAgICAgICAgICAgIC8vIGlDQ1AgY2h1bmsgc2hvdWxkIG5vdCBiZSBwcmVzZW50LgoKICAgICAgICAgICAgLy8gY2hhcmxlcwogICAgICAgIH0KCiAgICAgICAgUGFsZXR0ZSBwYWxldHRlID0gbnVsbDsKICAgICAgICBpZiAoY29sb3JUeXBlID09IENPTE9SX1RZUEVfSU5ERVhFRF9DT0xPUikKICAgICAgICB7CiAgICAgICAgICAgIC8vIFBMVEUgTm8gQmVmb3JlIGZpcnN0IElEQVQKCiAgICAgICAgICAgIGludCBtYXhfY29sb3JzID0gaGFzQWxwaGEgPyAyNTUgOiAyNTY7CgogICAgICAgICAgICBwYWxldHRlID0gbmV3IE1lZGlhbkN1dFF1YW50aXplcih0cnVlKS5wcm9jZXNzKHNyYywgbWF4X2NvbG9ycywKICAgICAgICAgICAgICAgICAgICB2ZXJib3NlKTsKICAgICAgICAgICAgLy8gUGFsZXR0ZSBwYWxldHRlMiA9IG5ldyBQYWxldHRlRmFjdG9yeSgpLm1ha2VQYWxldHRlU2ltcGxlKHNyYywKICAgICAgICAgICAgLy8gbWF4X2NvbG9ycyk7CgogICAgICAgICAgICAvLyBwYWxldHRlLmR1bXAoKTsKCiAgICAgICAgICAgIHdyaXRlQ2h1bmtQTFRFKG9zLCBwYWxldHRlKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgT2JqZWN0IHBpeGVsRGVuc2l0eU9iaiA9IHBhcmFtcy5nZXQoUEFSQU1fS0VZX1BJWEVMX0RFTlNJVFkpOwogICAgICAgIGlmIChwaXhlbERlbnNpdHlPYmogaW5zdGFuY2VvZiBQaXhlbERlbnNpdHkpCiAgICAgICAgewogICAgICAgICAgICBQaXhlbERlbnNpdHkgcGl4ZWxEZW5zaXR5ID0gKFBpeGVsRGVuc2l0eSlwaXhlbERlbnNpdHlPYmo7CiAgICAgICAgICAgIGlmIChwaXhlbERlbnNpdHkuaXNVbml0bGVzcygpKSB7CiAgICAgICAgICAgICAgICB3cml0ZUNodW5rUEhZUyhvcywgKGludClNYXRoLnJvdW5kKHBpeGVsRGVuc2l0eS5nZXRSYXdIb3Jpem9udGFsRGVuc2l0eSgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgKGludClNYXRoLnJvdW5kKHBpeGVsRGVuc2l0eS5nZXRSYXdWZXJ0aWNhbERlbnNpdHkoKSksIChieXRlKTApOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgd3JpdGVDaHVua1BIWVMob3MsIChpbnQpTWF0aC5yb3VuZChwaXhlbERlbnNpdHkuaG9yaXpvbnRhbERlbnNpdHlNZXRyZXMoKSksCiAgICAgICAgICAgICAgICAgICAgICAgIChpbnQpTWF0aC5yb3VuZChwaXhlbERlbnNpdHkudmVydGljYWxEZW5zaXR5TWV0cmVzKCkpLCAoYnl0ZSkxKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKHBhcmFtcy5jb250YWluc0tleShQQVJBTV9LRVlfWE1QX1hNTCkpCiAgICAgICAgewogICAgICAgICAgICBTdHJpbmcgeG1wWG1sID0gKFN0cmluZykgcGFyYW1zLmdldChQQVJBTV9LRVlfWE1QX1hNTCk7CiAgICAgICAgICAgIHdyaXRlQ2h1bmtYbXBpVFh0KG9zLCB4bXBYbWwpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHBhcmFtcy5jb250YWluc0tleShQQVJBTV9LRVlfUE5HX1RFWFRfQ0hVTktTKSkKICAgICAgICB7CiAgICAgICAgICAgIExpc3Q8UG5nVGV4dD4gb3V0cHV0VGV4dHMgPSAoTGlzdDxQbmdUZXh0PikgcGFyYW1zLmdldChQQVJBTV9LRVlfUE5HX1RFWFRfQ0hVTktTKTsKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBvdXRwdXRUZXh0cy5zaXplKCk7IGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgUG5nVGV4dCB0ZXh0ID0gb3V0cHV0VGV4dHMuZ2V0KGkpOwogICAgICAgICAgICAgICAgaWYgKHRleHQgaW5zdGFuY2VvZiBQbmdUZXh0LnRFWHQpCiAgICAgICAgICAgICAgICAgICAgd3JpdGVDaHVua3RFWHQob3MsIChQbmdUZXh0LnRFWHQpIHRleHQpOwogICAgICAgICAgICAgICAgZWxzZSBpZiAodGV4dCBpbnN0YW5jZW9mIFBuZ1RleHQuelRYdCkKICAgICAgICAgICAgICAgICAgICB3cml0ZUNodW5relRYdChvcywgKFBuZ1RleHQuelRYdCkgdGV4dCk7CiAgICAgICAgICAgICAgICBlbHNlIGlmICh0ZXh0IGluc3RhbmNlb2YgUG5nVGV4dC5pVFh0KQogICAgICAgICAgICAgICAgICAgIHdyaXRlQ2h1bmtpVFh0KG9zLCAoUG5nVGV4dC5pVFh0KSB0ZXh0KTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW1hZ2VXcml0ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbmtub3duIHRleHQgdG8gZW1iZWQgaW4gUE5HOiAiICsgdGV4dCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHsKICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoIndyaXRpbmcgSURBVCIpOwoKICAgICAgICAgICAgLy8gSURBVCBZZXMgTXVsdGlwbGUgSURBVCBjaHVua3Mgc2hhbGwgYmUgY29uc2VjdXRpdmUKCiAgICAgICAgICAgIGJ5dGUgdW5jb21wcmVzc2VkW107CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEJ5dGVBcnJheU91dHB1dFN0cmVhbSBiYW9zID0gbmV3IEJ5dGVBcnJheU91dHB1dFN0cmVhbSgpOwoKICAgICAgICAgICAgICAgIGJvb2xlYW4gdXNlQWxwaGEgPSBjb2xvclR5cGUgPT0gQ09MT1JfVFlQRV9HUkVZU0NBTEVfV0lUSF9BTFBIQQogICAgICAgICAgICAgICAgICAgICAgICB8fCBjb2xvclR5cGUgPT0gQ09MT1JfVFlQRV9UUlVFX0NPTE9SX1dJVEhfQUxQSEE7CgogICAgICAgICAgICAgICAgaW50IHJvd1tdID0gbmV3IGludFt3aWR0aF07CiAgICAgICAgICAgICAgICBmb3IgKGludCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vIERlYnVnLmRlYnVnKCJ5IiwgeSArICIvIiArIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgc3JjLmdldFJHQigwLCB5LCB3aWR0aCwgMSwgcm93LCAwLCB3aWR0aCk7CgogICAgICAgICAgICAgICAgICAgIGJ5dGUgZmlsdGVyX3R5cGUgPSBGSUxURVJfVFlQRV9OT05FOwogICAgICAgICAgICAgICAgICAgIGJhb3Mud3JpdGUoZmlsdGVyX3R5cGUpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IHggPSAwOyB4IDwgd2lkdGg7IHgrKykKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGludCBhcmdiID0gcm93W3hdOwoKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhbGV0dGUgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IGluZGV4ID0gcGFsZXR0ZS5nZXRQYWxldHRlSW5kZXgoYXJnYik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYW9zLndyaXRlKDB4ZmYgJiBpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgYWxwaGEgPSAweGZmICYgKGFyZ2IgPj4gMjQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IHJlZCA9IDB4ZmYgJiAoYXJnYiA+PiAxNik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgZ3JlZW4gPSAweGZmICYgKGFyZ2IgPj4gOCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgYmx1ZSA9IDB4ZmYgJiAoYXJnYiA+PiAwKTsKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNHcmF5c2NhbGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IGdyYXkgPSAocmVkICsgZ3JlZW4gKyBibHVlKSAvIDM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYoeT09MCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoImdyYXk6ICIgKyB4ICsgIiwgIiArIHkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICIgYXJnYjogMHgiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKyBJbnRlZ2VyLnRvSGV4U3RyaW5nKGFyZ2IpICsgIiBncmF5OiAweCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyArIEludGVnZXIudG9IZXhTdHJpbmcoZ3JheSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIERlYnVnLmRlYnVnKHggKyAiLCAiICsgeSArICIgZ3JheSIsIGdyYXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIERlYnVnLmRlYnVnKHggKyAiLCAiICsgeSArICIgZ3JheSIsIGdyYXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlYnVnLmRlYnVnKHggKyAiLCAiICsgeSArICIgZ3JheSIsIGdyYXkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICIgIiArIEludGVnZXIudG9IZXhTdHJpbmcoZ3JheSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlYnVnLmRlYnVnKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhb3Mud3JpdGUoZ3JheSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYW9zLndyaXRlKHJlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFvcy53cml0ZShncmVlbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFvcy53cml0ZShibHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VBbHBoYSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYW9zLndyaXRlKGFscGhhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHVuY29tcHJlc3NlZCA9IGJhb3MudG9CeXRlQXJyYXkoKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoInVuY29tcHJlc3NlZCIsIHVuY29tcHJlc3NlZC5sZW5ndGgpOwoKICAgICAgICAgICAgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGJhb3MgPSBuZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CiAgICAgICAgICAgIERlZmxhdGVyT3V0cHV0U3RyZWFtIGRvcyA9IG5ldyBEZWZsYXRlck91dHB1dFN0cmVhbShiYW9zKTsKICAgICAgICAgICAgaW50IGNodW5rX3NpemUgPSAyNTYgKiAxMDI0OwogICAgICAgICAgICBmb3IgKGludCBpbmRleCA9IDA7IGluZGV4IDwgdW5jb21wcmVzc2VkLmxlbmd0aDsgaW5kZXggKz0gY2h1bmtfc2l6ZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaW50IGVuZCA9IE1hdGgubWluKHVuY29tcHJlc3NlZC5sZW5ndGgsIGluZGV4ICsgY2h1bmtfc2l6ZSk7CiAgICAgICAgICAgICAgICBpbnQgbGVuZ3RoID0gZW5kIC0gaW5kZXg7CgogICAgICAgICAgICAgICAgZG9zLndyaXRlKHVuY29tcHJlc3NlZCwgaW5kZXgsIGxlbmd0aCk7CiAgICAgICAgICAgICAgICBkb3MuZmx1c2goKTsKICAgICAgICAgICAgICAgIGJhb3MuZmx1c2goKTsKCiAgICAgICAgICAgICAgICBieXRlIGNvbXByZXNzZWRbXSA9IGJhb3MudG9CeXRlQXJyYXkoKTsKICAgICAgICAgICAgICAgIGJhb3MucmVzZXQoKTsKICAgICAgICAgICAgICAgIGlmIChjb21wcmVzc2VkLmxlbmd0aCA+IDApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoImNvbXByZXNzZWQiLCBjb21wcmVzc2VkLmxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgd3JpdGVDaHVua0lEQVQob3MsIGNvbXByZXNzZWQpOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgfQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBkb3MuZmluaXNoKCk7CiAgICAgICAgICAgICAgICBieXRlIGNvbXByZXNzZWRbXSA9IGJhb3MudG9CeXRlQXJyYXkoKTsKICAgICAgICAgICAgICAgIGlmIChjb21wcmVzc2VkLmxlbmd0aCA+IDApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gRGVidWcuZGVidWcoImNvbXByZXNzZWQgZmluYWwiLCBjb21wcmVzc2VkLmxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgd3JpdGVDaHVua0lEQVQob3MsIGNvbXByZXNzZWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB7CiAgICAgICAgICAgIC8vIElFTkQgTm8gU2hhbGwgYmUgbGFzdAoKICAgICAgICAgICAgd3JpdGVDaHVua0lFTkQob3MpOwogICAgICAgIH0KCiAgICAgICAgLyoKICAgICAgICAgKiBBbmNpbGxhcnkgY2h1bmtzIChuZWVkIG5vdCBhcHBlYXIgaW4gdGhpcyBvcmRlcikgQ2h1bmsgbmFtZSBNdWx0aXBsZQogICAgICAgICAqIGFsbG93ZWQgT3JkZXJpbmcgY29uc3RyYWludHMgY0hSTSBObyBCZWZvcmUgUExURSBhbmQgSURBVCBnQU1BIE5vCiAgICAgICAgICogQmVmb3JlIFBMVEUgYW5kIElEQVQgaUNDUCBObyBCZWZvcmUgUExURSBhbmQgSURBVC4gSWYgdGhlIGlDQ1AgY2h1bmsKICAgICAgICAgKiBpcyBwcmVzZW50LCB0aGUgc1JHQiBjaHVuayBzaG91bGQgbm90IGJlIHByZXNlbnQuIHNCSVQgTm8gQmVmb3JlIFBMVEUKICAgICAgICAgKiBhbmQgSURBVCBzUkdCIE5vIEJlZm9yZSBQTFRFIGFuZCBJREFULiBJZiB0aGUgc1JHQiBjaHVuayBpcyBwcmVzZW50LAogICAgICAgICAqIHRoZSBpQ0NQIGNodW5rIHNob3VsZCBub3QgYmUgcHJlc2VudC4gYktHRCBObyBBZnRlciBQTFRFOyBiZWZvcmUgSURBVAogICAgICAgICAqIGhJU1QgTm8gQWZ0ZXIgUExURTsgYmVmb3JlIElEQVQgdFJOUyBObyBBZnRlciBQTFRFOyBiZWZvcmUgSURBVCBwSFlzCiAgICAgICAgICogTm8gQmVmb3JlIElEQVQgc1BMVCBZZXMgQmVmb3JlIElEQVQgdElNRSBObyBOb25lIGlUWHQgWWVzIE5vbmUgdEVYdAogICAgICAgICAqIFllcyBOb25lIHpUWHQgWWVzIE5vbmUKICAgICAgICAgKi8KCiAgICAgICAgb3MuY2xvc2UoKTsKICAgIH0gLy8gdG9kbzogZmlsdGVyIHR5cGVzCiAgICAvLyBwcm9wZXIgY29sb3VyIHR5cGVzCiAgICAvLyBzcmdiLCBldGMuCn0K